Flask_Mongoengine: 使用聚合后不是 mongoengine object
Flask_Mongoengine: Not a mongoengine object after using aggregate
当 aggregate
与 mongoengine 一起使用时,它 return 一个 CommandCursor 而不是 mongoengine object 列表,这意味着 mongonengine 并没有真正被使用,
例如:如果某些文档没有标题字段,则会引发错误。如何将我的结果转换为 mongoengine object?
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 function的快捷方式。
从 aggregate
返回的文档可能涉及某些 $group
或其他阶段,这意味着它们与您的对象模型无关,因此 mongoengine 无法将它们转换为 mongoengine 对象。
在您的管道中,您使用 $project
阶段来 return 一种只有 name
和 brating
字段的新型文档。
Mongoengine 无法在这里做你想做的事,所以你有几个选择:
将 brating
字段存储在 Post
文档中。创建 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 一起使用时,它 return 一个 CommandCursor 而不是 mongoengine object 列表,这意味着 mongonengine 并没有真正被使用,
例如:如果某些文档没有标题字段,则会引发错误。如何将我的结果转换为 mongoengine object?
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 function的快捷方式。
从 aggregate
返回的文档可能涉及某些 $group
或其他阶段,这意味着它们与您的对象模型无关,因此 mongoengine 无法将它们转换为 mongoengine 对象。
在您的管道中,您使用 $project
阶段来 return 一种只有 name
和 brating
字段的新型文档。
Mongoengine 无法在这里做你想做的事,所以你有几个选择:
将
brating
字段存储在Post
文档中。创建 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]