对ListField中引用的项进行Mongoengine ORM过滤

时间:2016-02-09 05:20:25

标签: mongodb pymongo mongoengine

使用MongoEngine考虑以下内容:

class Files(Document):
    name = StringField()
    access_time = DateTimeField()
    size = IntField()

class Folders(Document):
    name = StringField()
    files = ListField(field=ReferenceField('Files'))

如果我希望将文件放在按某个属性(name / access_time / size)过滤的文件夹中,有什么好办法?

我可以遍历列表(可能使用no_cache()),但是如果对象更多,则需要花费很多时间。

如何优雅地过滤在MongoEngine中具有引用的ListField?

1 个答案:

答案 0 :(得分:0)

文档引用仅存储为mongodb中的ObjectID列表,因此您需要使用mongoengine取消引用它们以进行任何类型的过滤。

您有三种方法可以解决这个问题:

将参考存储在Files对象:

class Files(Document):
    name = StringField()
    access_time = DateTimeField()
    size = IntField()
    folder = ReferenceField(Folders)

folder = Folders.objects.first()
big_files = Files.objects(size__gt=500,folder=folder).all()

将文件存储为嵌入式文档:

class Files(EmbeddedDocument):
    name = StringField()
    access_time = DateTimeField()
    size = IntField()

class Folders(Document):
    name = StringField()
    files = EmbeddedDocumentListField(Files)

使用aggregation framework

pipeline = [
    {"$unwind": "$files"},
    {"$lookup":
        {
            "from": "files",
            "localField": "files",
            "foreignField": "_id",
            "as": "files"
        }},
    {"$unwind": "$files"},
    {"$match": {"files.size": {"$gt": 500}}},
    {"$group": {
        "_id": "$_id",
        "name": {"$first": "$name"},
        "files": {"$push": "$files"}
    }},

]

folders = Folders.objects.aggregate(*pipeline)

您使用的将基于您的实际应用程序而不是聚合管道上的$lookup仅可从mongodb版本3.2获得,并且不适用于分片集合。

相关问题