【问题标题】:Need help in querying mongodb在查询 mongodb 时需要帮助
【发布时间】:2020-11-10 14:59:20
【问题描述】:

我有一些具有以下结构的文档。见附图。

document structure

每个文档都包含一个“FileMeta”对象数组,每个 FileMeta 对象都包含一个“StatusHistory”对象数组。我试图只获取包含 StatusCode 等于 4 并且 TimeStamp 大于某个日期时间的 FileMetas。

尝试了以下查询,但它只返回每个文档的第一个 FileMeta 元素。

db.getCollection('Collection').find({'ExternalParams.RequestingApplication':'aaa.bbb'},
                 { "FileMeta": { $elemMatch: { "StatusHistory":{ $elemMatch:{ "StatusCode": 4, "TimeStamp": { $gt: ISODate("2020-06-28T11:02:26.542Z")} } } } }} )

我做错了什么?

这是文档结构:

{
"_id" : ObjectId("5ef84e2ec08abf38b0043ab4"),
"FileMeta" : [ 
    {            
        "StatusHistory" : [ 
            {
                "StatusCode" : 0,
                "StatusDesc" : "New File",
                "TimeStamp" : ISODate("2020-06-28T11:00:46.286Z")
            }, 
            {
                "StatusCode" : 2,
                "StatusDesc" : "stby",
                "TimeStamp" : ISODate("2020-06-28T11:02:20.400Z")
            }, 
            {
                "StatusCode" : 4,
                "StatusDesc" : "success",
                "TimeStamp" : ISODate("2020-06-28T11:02:26.937Z")
            }
        ]
    }, 
    {
        
        "StatusHistory" : [ 
            {
                "StatusCode" : 0,
                "StatusDesc" : "New File",
                "TimeStamp" : ISODate("2020-06-28T11:00:46.286Z")
            }, 
            {
                "StatusCode" : 2,
                "StatusDesc" : "stby",
                "TimeStamp" : ISODate("2020-06-28T11:02:20.617Z")
            }, 
            {
                "StatusCode" : 4,
                "StatusDesc" : "success",
                "TimeStamp" : ISODate("2020-06-28T11:02:26.542Z")
            }
        ]
    }
],

}

我只想返回包含满足以下条件的 StatusHistory 的 FileMeta 对象:StatusCode = 4 和 TimeStamp > SomeDateTime

【问题讨论】:

    标签: arrays mongodb search


    【解决方案1】:

    对不起,伙计,我最近很忙。希望你已经解决了你的问题。无论如何,我认为我找到了解决方案。

    正如您在this link 上看到的那样,该示例显示默认情况下$elemMatch 运算符会在任何元素匹配的情况下返回整个数组。

    例如,考虑以下集合:

    { _id: 1, results: [ { product: "abc", score: 10 }, { product: "xyz", score: 5 } ] }
    { _id: 2, results: [ { product: "abc", score: 8 }, { product: "xyz", score: 7 } ] }
    { _id: 3, results: [ { product: "abc", score: 7 }, { product: "xyz", score: 8 } ] }
    

    如果你做如下查询,例如:

    db.survey.find(
       { results: { $elemMatch: { product: "xyz", score: { $gte: 8 } } } }
    )
    

    输出将是:

    { "_id" : 3, "results" : [ { "product" : "abc", "score" : 7 }, { "product" : "xyz", "score" : 8 } ] }
    

    不是:

    { "_id" : 3, "results" : [{ "product" : "xyz", "score" : 8 }]}
    

    也就是说,如果您只想返回与指定查询匹配的数组中的文档,则必须将db.collection.aggregate() 函数与$unwind$match 运算符一起使用。

    下面的查询会给你你想要的。

    查询:

    db.collection.aggregate([
        {"$unwind" : "$FileMeta"},
        {"$unwind" : "$FileMeta.StatusHistory"},
        {
            "$match" : {
                "FileMeta.StatusHistory.StatusCode" : 4,
                "FileMeta.StatusHistory.TimeStamp" : {"$gte" : ISODate("2020-06-28T11:02:26.937Z")}
            }
        }
    ]).pretty()
    

    结果:

    {
            "_id" : ObjectId("5ef84e2ec08abf38b0043ab4"),
            "FileMeta" : {
                    "StatusHistory" : {
                            "StatusCode" : 4,
                            "StatusDesc" : "success",
                            "TimeStamp" : ISODate("2020-06-28T11:02:26.937Z")
                    }
            }
    }
    

    最后一个提示。考虑将您的建模更改为看起来像展开文档的东西,并记住一个文档应该等同于普通关系数据库中的一行。因此,请避免在单个文档中存储应该在“几行”上的信息。

    有用的链接:

    【讨论】:

    • 嗨佩德罗感谢您的及时回复。我已经尝试过这些查询。问题是它们还返回一个“FileMeta”对象,其中包括一个“StatusHistory”,其时间戳等于查询中包含的日期。即它不会以毫秒为单位按日期时间过滤:“2020-06-28T11:02:26.542Z”。也许它与投影有关。如何仅获取满足查询条件的“FileMeta”对象?
    • 你好,伙计。我已经更新了解决方案。请检查它是否有效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-14
    • 2021-08-02
    • 2018-07-18
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    相关资源
    最近更新 更多