基于最后一个索引的列表嵌入字段的Mongoengine过滤器查询
Mongoengine filter query on list embedded field based on last index
我在 Django 中使用 Mongoengine。
我的模型中有一个嵌入字段。那是嵌入文档的列表字段。
import mongoengine
class OrderStatusLog(mongoengine.EmbeddedDocument):
status_code = mongoengine.StringField()
class Order(mongoengine.DynamicDocument):
incr_id = mongoengine.SequenceField()
status = mongoengine.ListField(mongoengine.EmbeddedDocumentField(OrderStatusLog))
现在我想根据 status
字段中的最后一个值过滤 Order
集合的结果。
例如Order.objects.filter(status__last__status_code="scode")
我想没有这样的东西__last
。我尝试了文档中提到的方法 http://docs.mongoengine.org/guide/querying.html#querying-lists
但没有用。
我可以通过遍历集合中的所有文档来解决这个问题,但效率不高,我们如何才能高效地编写此查询。
我不确定 MongoEngine 是否可以做到这一点(目前)。据我所知,您需要使用聚合管道。
在Mongoshell中,使用'$slice' and the $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.
我在 Django 中使用 Mongoengine。
我的模型中有一个嵌入字段。那是嵌入文档的列表字段。
import mongoengine
class OrderStatusLog(mongoengine.EmbeddedDocument):
status_code = mongoengine.StringField()
class Order(mongoengine.DynamicDocument):
incr_id = mongoengine.SequenceField()
status = mongoengine.ListField(mongoengine.EmbeddedDocumentField(OrderStatusLog))
现在我想根据 status
字段中的最后一个值过滤 Order
集合的结果。
例如Order.objects.filter(status__last__status_code="scode")
我想没有这样的东西__last
。我尝试了文档中提到的方法 http://docs.mongoengine.org/guide/querying.html#querying-lists
但没有用。
我可以通过遍历集合中的所有文档来解决这个问题,但效率不高,我们如何才能高效地编写此查询。
我不确定 MongoEngine 是否可以做到这一点(目前)。据我所知,您需要使用聚合管道。
在Mongoshell中,使用'$slice' and the $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.