我正在尝试获取符合以下条件的所有文档,但结果似乎不正确。
条件:发行日期与给定范围相匹配且该发行时间表有效的电影
isActive = true和releaseDate> = 2020-04-20和releaseDate <= 2020-04-21
每个文档的类型都是Movie,其中包含movieTimeline对象的列表,每个movieTimeline都有一个isActive和releaseDate属性。 任何时候,单个movieTimeline都可以在文档中处于活动状态。
文档的结构-
@Document
public class Movie extends BaseDocument
{
private String name;
private List<MovieTimeline> movieTimelines;
...
public class MovieTimeline
{
private Boolean isActive;
private LocalDateTime releaseDate;
private String description;
...
发布日期属性在Java中的类型为 LocalDateTime ,并以2020-04-20T05:00:00.000 + 00:00的格式存储在数据库中。
这是我尝试检索数据的代码-
@Repository
public interface MovieRepository extends MongoRepository<Movie,String>
{
List<Movie> findByMovieTimelines_ReleaseDateBetweenAndMovieTimelines_IsActive(LocalDateTime from, LocalDateTime to, boolean isActive);
}
样本数据-
{
"id": "abc",
"name": "Rango",
"movieTimelines": [{
"isActive": false,
"releaseDate": "2020-02-10T11:30:00",
"description": "ORIGINAL TIMELINE"
}, {
"isActive": true,
"releaseDate": "2020-06-15T10:30:00",
"description": "New Timeline created on 03/10/2020"
}
]
}, {
"id": "abcv",
"name": "Fight Club",
"movieTimelines": [{
"isActive": false,
"releaseDate": "2020-02-10T11:30:00",
"description": "ORIGINAL TIMELINE"
}, {
"isActive": true,
"releaseDate": "2020-05-18T10:30:00",
"description": "New Timeline created on 02/05/2020"
}
]
}, {
"id": "asd",
"name": "Death Note",
"movieTimelines": [{
"isActive": false,
"releaseDate": "2020-03-09T10:30:00",
"description": "ORIGINAL TIMELINE"
}, {
"isActive": false,
"releaseDate": "2020-03-16T10:30:00",
"description": "New Timeline created on 02/05/2020"
}, {
"isActive": false,
"releaseDate": "2020-04-20T10:30:00",
"description": "New Timeline created on 03/06/2020"
}, {
"isActive": true,
"releaseDate": "2020-04-20T10:30:00",
"description": "New Timeline created on 03/06/2020"
}
]
}, {
"id": "gfj",
"name": "Andhadhun",
"movieTimelines": [{
"isActive": false,
"releaseDate": "2020-04-13T10:30:00",
"description": "ORIGINAL TIMELINE"
}, {
"isActive": true,
"releaseDate": "2020-07-20T10:30:00",
"description": "New Timeline created on 03/09/2020"
}
]
}, {
"id": "nojh",
"name": "Evan Almighty",
"movieTimelines": [{
"isActive": true,
"releaseDate": "2020-04-20T10:30:00",
"description": "ORIGINAL TIMELINE"
}
]
}
预期-
{
"id": "asd",
"name": "Death Note",
"movieTimelines": [{
"isActive": false,
"releaseDate": "2020-03-09T10:30:00",
"description": "ORIGINAL TIMELINE"
}, {
"isActive": false,
"releaseDate": "2020-03-16T10:30:00",
"description": "New Timeline created on 02/05/2020"
}, {
"isActive": false,
"releaseDate": "2020-04-20T10:30:00",
"description": "New Timeline created on 03/06/2020"
}, {
"isActive": true,
"releaseDate": "2020-04-20T10:30:00",
"description": "New Timeline created on 03/06/2020"
}
]
},{
"id": "nojh",
"name": "Evan Almighty",
"movieTimelines": [{
"isActive": true,
"releaseDate": "2020-04-20T10:30:00",
"description": "ORIGINAL TIMELINE"
}
]
}
MongoDB是否有任何过滤器或运算符可用于在单个查询中获取这些文档?
答案 0 :(得分:1)
MongoDB提供$elemMatch投影运算符,该运算符应该能够满足您的条件。
尤其是,您的文档由一系列文档组成。因此,这里是另一个reference,您可以用来构造针对此类数据的查询。
这是我对您的病情和样本数据进行测试时发现的。我的查询使用的是Mongo Shell,而不是Java / Spring,因此请以所需的语言重写。
由于只想获取具有活动电影时间轴的文档,因此“ movieTimelines”中的“ isActive”属性必须为true。使用以下查询可以单独满足此条件:
db.collectionName.find({ "movieTimelines": { $elemMatch: { "isActive": true } } })
发布日期也需要在给定范围内,这意味着查询需要处理“ movieTimelines”中的“ releaseDate”属性。可以通过以下方式查询此条件:
db.collectionName.find({ "movieTimelines": { $elemMatch: { "releaseDate": { $gte: ISODate("2020-04-20T00:00:00"), $lte: ISODate("2020-04-21T00:00:00") } } } })
或
db.collectionName.find({ "movieTimelines": { $elemMatch: { "releaseDate": { $gte: ISODate("2020-04-20"), $lte: ISODate("2020-04-21") } } } })
对于上述查询,“ releaseDate”值是“ ISODate()”对象,而不是数据库中的字符串。可以使用toDate,dateFromString等聚合器将字符串转换为ISODate对象。
即使“ releaseDate”值是字符串,如果条件中的数据类型更改为字符串,查询也将起作用。这可能不是一个好习惯。
db.collectionName.find({ "movieTimelines": { $elemMatch: { "releaseDate": { $gte: "2020-04-20", $lte: "2020-04-21" } } } })
因此,要满足这两个条件,需要将两个查询合并为一个:
db.collectionName.find({ "movieTimelines": { $elemMatch: { "isActive": true, "releaseDate": { $gte: ISODate("2020-04-20T00:00:00"), $lte: ISODate("2020-04-21T00:00:00") } } } })
我希望这能回答您的问题。