【问题标题】:Match embedded Documents by Regular expression with Mongoengine使用 Mongoengine 通过正则表达式匹配嵌入的文档
【发布时间】:2016-01-03 00:37:30
【问题描述】:

我有一个文档列表,每个包含 50 个(可能会有所不同)嵌入式文档。现在我想查询所有包含以特定模式开头的 id 的 EmbeddedDocument(跨所有 Document)。

class Container(Document):
    list = EmbeddedDocumentListField(Data)

class Data(EmbeddedDocument):
    id=StringField(required=True, primary_key=True)

现在查询(或类似startswith的东西)将在Data的'id'上。

【问题讨论】:

  • 请不要建议查看所有文档中的每个嵌入文档。我们负担不起 O(m*n)

标签: python mongodb mongodb-query pymongo mongoengine


【解决方案1】:

作为嵌入字段,您需要使用 "double underscore" __ 来表示与原生 "dot notation" 相比的字段的嵌入语法以及字符串的 startswithistartswith 修饰符:

Container.objects(list__id__startswith="AAA")

否则,如果您需要“真正的”正则表达式而不是允许的快捷方式,那么您可以将 __raw__ 修饰符与“原始”MongoDB 语法查询一起使用:

Container.objects(__raw__={ "list.id": ,re.compile('^AAA', re.IGNORECASE) })

或者可能是"list._id",这取决于字段名称是如何被告知为嵌入对象序列化的。

无论哪种方式本质上都是将查询卸载到数据库,在那里它可以使用它的功能来确定匹配。

当然有一个基本的mongoengine 限制,即无法简单地投影匹配的数组元素。这是关于如何读取和实例化类数据的全部内容。

您可以使用.aggregate() 方法返回“原始python 对象”作为替代实现的类:

Container._get_collection().aggregate({
    { "$match": { "list.id": ,re.compile('^AAA', re.IGNORECASE) } },
    { "$unwind": "$list" },
    { "$match": { "list.id": ,re.compile('^AAA', re.IGNORECASE) } },
    { "$group": {
        "_id": "$_id",
        "list": { "$push": "$list" }
    }}
])

因此不再是相同的 class 定义,但也没有什么可以阻止您提供原始数据以实例化所需类的新对象(如果需要)。

【讨论】:

  • 我做了 Container.objects(list__id__startswith="AAA"),如果它的任何嵌入式文档与模式匹配,它会返回所有 Container。那么我们是否应该查看每个容器中的每个嵌入式文档以制作数据列表
  • @KumarNitin 这是mongoengine 的限制,因为它不会更改返回的文档以仅返回匹配的数组元素。相同的“基本上”适用于 MongoDB 本身,但是在原始形式中,您可以使用“投影”返回匹配的“元素”(单数)。 MongoEngine 本身不会将其作为第一类对象,但.aggregate() 可以返回一个仅包含匹配“元素”的“普通”对象。
  • 如果我们对百万嵌入文档(每个文档包含 50/100 EmbeddedDocument)执行此操作会影响性能吗?
  • @KumarNitin 一般查询很少,因为 MongoDB 在这方面非常聪明。如果您真的只需要过滤掉匹配的数组项,我添加了一个使用.aggregate() 的示例,其中还有其他用于处理的$unwind 的替代方案,但在使用正则表达式时不是一个真正的选项匹配。 $unwind 可以增加开销,因为它本质上将数组“分解”为离散文档,因此可以执行其他操作。 50-100相当小,更多的是看整体匹配影响有多大。
  • 这真的很有帮助。谢谢老哥!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-11
  • 1970-01-01
相关资源
最近更新 更多