我有一系列的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] 删除。
我来说两句