通过正则表达式将嵌入式文档与Mongoengine

时间:2015-10-06 07:27:16

标签: python mongodb mongodb-query pymongo mongoengine

我有一个Document列表,每个包含50个(这可能会有所不同)EmbeddedDocument。现在我想查询包含以某种模式开头的id的所有EmbeddedDocument(在所有Document中)。

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

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

现在查询(或类似于startwith)将在数据的“id”上。

1 个答案:

答案 0 :(得分:3)

作为嵌入字段,您需要使用"double underscore" __的嵌入式语法来表示与原始"dot notation"以及startswith或字符串istartswith修饰符:

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,但如果需要,也没有什么可以阻止你提供原始数据来实例化所需类的新对象。