MongoDB / MongoEngine-查询列表中的项目

奥科博科

我有一系列的MongoDB文件,如下所示:

{
 "_id" : ObjectId("53992c7d02b8756437f81cba"),
 "account_id" : ObjectId("5397929402b8751ae8a32349"),
 "event_history" : [ 
                     [ 0, ISODate("2014-06-12T04:28:45.684Z") ],
                     [ 0, ISODate("2014-06-11T04:28:45.684Z") ],
                     [ 1, ISODate("2014-05-12T04:28:45.684Z") ] 
                   ],
 "status" : 1
}

是否有可能返回event_history的其中有一个0是(在MongoEngine)的第一个元素?

我想得到这个:

[ 0, ISODate("2014-06-12T04:28:45.684Z") ],
[ 0, ISODate("2014-06-11T04:28:45.684Z") ],

这是我尝试过的查询,但不起作用:

Record.objects(id=ObjectId("53992c7d02b8756437f81cba"), event_history__in=[0])

尼尔·伦恩

好问题。这里有些事情使这变得不那么简单。

首先要提到的是嵌套数组/列表不是标准的django fair,但是您可以深入__raw__探讨MongoEngine提供语法,因为它确实需要更多特定于MongoDB的东西。

就是说,即使如此,您要在此处执行的过滤类型甚至超出了标准MongoDB.find()类型查询的范围,因为您希望匹配多个内部数组成员,然后在结果中“过滤”返回的成员。

实际上,这不仅对嵌套数组非常棘手,而且对于仅使用聚合框架也可以完成的事情来说非常棘手。尽管有任何明确的文档说明,您仍可以通过使用._get_collection()类上方法访问集合的“原始” pymongo驱动程序函数来使用MongoEngine

评论说明:

Record._get_collection().aggregate([
    # Match only those documents that would meet the condition
    { "$match": { 
        "event_history": { 
            "$elemMatch": { 
                "$elemMatch": {"$in": [0] }
            }
        }
    }},

    # Unwind the event history array, top level
    { "$unwind": "$event_history" },

    # Make a copy of the inner array
    { "$project": {
        "account_id": 1,
        "event_history": 1,
        "status": 1,
        "copy": "$event_history"
    }},

    # Unwind that copy
    { "$unwind": "$copy" },

    # Match the numeric 0 elements only, filters non-matches
    { "$match": { "copy": 0 } },

    # Group back to the original document
    { "$group": {
        "_id": "$_id",
        "account_id": { "$first": "$account_id" },
        "event_history": { "$push": "$event_history" },
        "status": { "$first": "$status" }
    }}
])

如果其中有多个数值可能是0,那么您需要知道它是第一个数值。因此,涉及更多一点:

Record._get_collection().aggregate([
    # Match only those documents that would meet the condition
    { "$match": { 
        "event_history": { 
            "$elemMatch": { 
                "$elemMatch": {"$in": [0] }
            }
        }
    }},

    # Unwind the event history array, top level
    { "$unwind": "$event_history" },

    # Make a copy of the inner array
    { "$project": {
        "account_id": 1,
        "event_history": 1,
        "status": 1,
        "copy": "$event_history"
    }},

    # Unwind that copy
    { "$unwind": "$copy" },

    # Group back the document keeping the "first" inner element only
    { "$group": {
        "_id": {
            "_id": "$_id",
            "account_id": "$account_id",
            "event_history": "$event_history",
            "status": "$status"
        },
        "copy": { "$first": "$copy" }
    }},

    # Match only where 0 to filter
    { "$match": { "copy": 0 } },

    # Group back to the original document
    { "$group": {
        "_id": "$_id._id",
        "account_id": { "$first": "$_id.account_id" },
        "event_history": { "$push": "$_id.event_history" },
        "status": { "$first": "$status" }
    }}
])

以及每种情况下的结果:

{
    "_id" : ObjectId("53992c7d02b8756437f81cba"),
    "account_id" : ObjectId("5397929402b8751ae8a32349"),
    "event_history" : [
            [ 0, ISODate("2014-06-11T04:28:45.684Z") ],
            [ 0, ISODate("2014-06-12T04:28:45.684Z") ]
    ],
    "status": 1
}

因此,是的,该过程看起来有点复杂,而且并非您想象的那样简单。但值得庆幸的是,有一种方法可以访问原始收集方法并使用聚合来解决此问题。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章