【问题标题】:To query documents - based on a property of an object which is part of a list within the document查询文档 - 基于对象的属性,该对象是文档中列表的一部分
【发布时间】:2020-04-05 00:19:06
【问题描述】:

我正在尝试获取所有符合以下条件的文档,但结果似乎不正确。

标准:发行日期与给定范围匹配且此发行时间表有效的电影

isActive=true 和 releaseDate >= 2020-04-20 和 releaseDate

每个文档都是Movie 类型,其中包含一个movieTimeline 对象列表,每个movieTimeline 都有一个isActive 和releaseDate 属性。 在任何时候,单个电影时间线都可以在文档中处于活动状态。

文档的结构 -

@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 格式存储在 DB 中。

这是我尝试检索数据的代码-

@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 是否有任何过滤器或运算符可用于在单个查询中获取这些文档?

【问题讨论】:

    标签: mongodb mongodb-query spring-data-mongodb


    【解决方案1】:

    MongoDB提供$elemMatch投影算子应该可以满足你的条件。

    特别是,您的文档由一组文档组成。所以这里有另一个reference,您可以使用它来构造此类数据的查询。

    这是我在使用您的状况和样本数据进行测试时发现的。我的查询是在 Mongo Shell 中,而不是 Java/Spring,所以请用所需的语言重写它。

    由于您只想获取那些具有活动电影时间线的文档,因此“movieTimelines”中的“isActive”属性必须为真。仅此条件就可以使用以下查询来满足:

    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") } } } })
    

    我希望这能回答你的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多