【问题标题】:Flask_Mongoengine: Not a mongoengine object after using aggregateFlask_Mongoengine:使用聚合后不是 mongoengine 对象
【发布时间】:2017-05-13 23:28:21
【问题描述】:

aggregate与mongoengine一起使用时,它返回一个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'>

【问题讨论】:

  • 可能值得发布一个新问题来解释为什么你需要在这里使用聚合。通常,聚合管道用于转换和组合多个文档,而不仅仅是检索它们。

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


【解决方案1】:

aggregate 函数只是底层pymongo function 的快捷方式。

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

就您的管道而言,您正在使用$project 阶段来返回只有namebrating 字段的新型文档。

Mongoengine 不能在这里做你想做的事,所以你有几个选择:

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

  • 接受您正在取回非 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]

【讨论】:

  • 问题是我必须使用aggregate来处理一些复杂的查询,mongoengine不能处理,有没有办法同时使用它们?
  • 为什么mongoengine不能处理查询?也许在问题中发布您的管道。
  • 我刚刚添加了流水线代码,请看一下如何使用 mongoengine 的 .objects 表示法。
  • 这很难回答,因为您没有给出complete question,但我已经添加了一些选项。您将无法使用 mongoengine 做您想做的事情,尽管在技术上可以实现您要求的内容,您必须自己编写它,因此可能更容易查看其他方法。
  • 谢谢。示例代码的解决方案正在处理我的案例,我仍然不确定哪种方法具有更好的性能?使用 mongoengine 对象然后对其进行迭代,计算新字段,对其进行排序,或使用 pymongo 的聚合,然后手动检查烧瓶模板中的每个字段。顺便说一句:我的收藏有大约 4000 个文档。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-26
  • 1970-01-01
  • 1970-01-01
  • 2016-04-29
  • 2014-08-16
  • 1970-01-01
  • 2010-10-22
相关资源
最近更新 更多