BLASK_MONGOENENGINE:使用汇总后不是Mongoengine对象



当将 aggregate与mongoengine一起使用时,它返回命令cursor而不是mongoengene对象列表,这意味着并未真正使用mongonengine,

例如:如果某些文档没有标题字段,则会增加错误。如何将结果转换为蒙古引擎对象?

class Post(Document):
    title = StringField(max_length=120, required=True)
    author = ReferenceField(User)
Host.objects()
# [<Post: Post object>, <Post: Post object>, ...]
pipeline = [
    {
        "$match": {
            'types': type,
        }
    },
    {
        "$project": {
            "name": 1,
            'brating': {
                "$divide": [
                    {"$add": ["$total_score", 60]},
                    {"$add": ["$total_votes", 20]}
                ]
            }
        }
    },
    {"$sort": {"brating": -1}},
    {"$limit": 100}
]
Host.objects.aggregate(*pipeline)
# <class 'pymongo.command_cursor.CommandCursor'>
list(Host.objects.aggregate(*pipeline))
# <class 'list'>

aggregate函数只是基础pymongo函数的快捷方式。

aggregate返回的文档可能涉及一些$group或其他阶段,这意味着它们与您的对象模型无关,因此MongoEngine无法将其转换为MongoEngine对象。

在管道的情况下,您使用的是$project阶段来返回仅具有namebrating字段的新型文档。

MongoEngine将无法在这里做您想做的事情,因此您有几个选择:

  • brating字段存储在Post文档上。在创建帖子以及$total_score$total_votes更新时,在0处初始化等级时,还会更新评级。

  • 接受您正在恢复非蒙加德对象并相应地处理它们。光标将产生正常的Python词典,然后您可以在客户端代码中访问post['name']post['brating']字段。

  • 使用普通的.objects查询并在客户端上排序。

如果您有很多文档,那么最后一步将是一个问题

posts = Post.objects(types=type).only("name", "total_score", "total_votes")
top_posts = sorted(list(posts),key=lambda p: (p.total_score+60)/(p.total_votes+20))[:100]

最新更新