我使用Mongoengine和Django。
我的模型中有一个嵌入字段。这是嵌入式文档的列表字段。
import mongoengine
class OrderStatusLog(mongoengine.EmbeddedDocument):
status_code = mongoengine.StringField()
class Order(mongoengine.DynamicDocument):
incr_id = mongoengine.SequenceField()
status = mongoengine.ListField(mongoengine.EmbeddedDocumentField(OrderStatusLog))
现在,我想根据Order
字段中的最后一个值,在status
集合上过滤结果。
e.g。 Order.objects.filter(status__last__status_code="scode")
我想没有__last
这样的事情。我尝试了文档http://docs.mongoengine.org/guide/querying.html#querying-lists中提到的方法
但是没有工作。
我可以通过循环遍历集合中的所有文档来解决这个问题,但这样做效率不高,我们如何才能有效地编写这个查询。
答案 0 :(得分:1)
我不确定MongoEngine能做到(还)。 AFAIK,您需要使用聚合管道。
在Mongo shell中,使用'$slice'和$arrayElemAt
运算符:
db.order.aggregate([{ $project: {last_status: { $arrayElemAt: [{ $slice: [ "$status", -1 ] }, 0 ]} }}, {$match: {'last_status.status_code':"scode"}} ])
在Python中:
pipeline = [
{'$project': {'last_status': { '$arrayElemAt': [{ '$slice': [ "$status", -1 ] }, 0 ]} }},
{'$match': {'last_status.status_code':'scode'}}
]
agg_cursor = Order.objects.aggregate(*pipeline)
result = [ Order.objects.get(id=order['_id']) for order in agg_cursor ]
这里的诀窍是objects.aggregate
提供PyMongo
光标,而不是MongoEngine
光标,因此如果您需要MongoEngine
个对象,则可以分两步进行:首先使用聚合框架过滤以获取匹配项的ID,然后通过MongoEngine
查询获取它们。
这就是我的工作。从我的测试中,它已被证明比获取所有内容并在python代码中过滤更有效。
如果有更简单的方法,我有兴趣了解它。否则,这可能是MongoEngine的功能请求。您可能想要打开问题there。