基于最后索引的列表嵌入字段上的Mongoengine过滤查询

时间:2016-05-09 13:24:51

标签: python mongodb pymongo mongoengine

我使用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中提到的方法 但是没有工作。

我可以通过循环遍历集合中的所有文档来解决这个问题,但这样做效率不高,我们如何才能有效地编写这个查询。

1 个答案:

答案 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