Flask_Mongoengine:使用聚合后不是mongoengine对象

时间:2016-12-29 15:58:04

标签: python python-3.x pymongo mongoengine flask-mongoengine

当使用mongoengine aggregate时,它会返回一个CommandCursor而不是mongoengine对象列表,这意味着真的没有使用mongonengine,

例如:如果某个文档没有标题字段,则会引发错误。如何将结果转换为mongoengine对象?

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'>

1 个答案:

答案 0 :(得分:1)

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

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

对于您的管道,您使用$project阶段来返回仅包含namebrating字段的新类型文档。

Mongoengine无法在这里做你想做的事情所以你有几个选择:

  • brating字段存储在Post文档中。创建帖子并更新$total_score$total_votes时,将评级初始化为0,同时更新评级。

  • 接受您正在取回非mongoengine对象并相应地处理它们。光标将生成普通的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]