【问题标题】:Mongoengine filter query on list embedded field based on last indexMongoengine过滤器查询基于最后一个索引的列表嵌入字段
【发布时间】:2016-09-04 03:49:00
【问题描述】:

我在 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中提到的方法 但没用。

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

【问题讨论】:

  • 我认为你应该标记你的问题 python 以便 1/ 它被列为 python 问题 2/ 它得到自动语法突出显示。 (或者,您可以在代码块之前指定<!-- language: lang-python -->stackoverflow.com/editing-help#syntax-highlighting

标签: python mongodb pymongo mongoengine


【解决方案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

【讨论】:

  • 感谢杰罗姆。我尝试了第二个及其工作。非常感谢。
猜你喜欢
  • 2016-08-28
  • 2019-05-05
  • 2018-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多