mongoengine - 如何根据ListField大小过滤查询

12 投票
2 回答
7338 浏览
提问于 2025-04-17 16:42

我有一个这样的模型:

class Like(EmbeddedDocument):
    user = ReferenceField(User,dbref=False)
    date = DateTimeField(default=datetime.utcnow,required=True)
    meta = {'allow_inheritance': False}

class Post(Document):
   name = StringField(max_length=120, required=True)
   likes = ListField(EmbeddedDocumentField(Like))

我想筛选出那些点赞超过20的帖子(也就是ListField的大小大于20)。我尝试用以下方式查询:

posts = Post.objects.filter(likes__size_gte=20)
posts = Post.objects.filter(likes_gte=20)
posts = Post.objects.filter(likes__gte=20)
posts = Post.objects.filter(likes__size_gte=20)

但是这些都不管用。

不过,如果我用精确匹配(ListField的大小正好是20个点赞),那就可以:

posts = Post.objects.filter(likes__size=20) 

有什么意见吗?

2 个回答

5

你不能用 $size 来处理一系列的值。

根据 Mongo 的网站:

$size 不支持值的范围。如果你想根据字段中元素的数量来选择文档,你需要创建一个计数字段,每当你往这个字段添加元素时,就把计数器加一。

这是一个相关问题的链接,帮助得出了这个答案:在 mongoDB 中删除数组字段大小小于 3 的文档

这是之前链接指向的 Mongo 文档页面,里面有上面提到的内容的详细说明: http://docs.mongodb.org/manual/reference/operator/size/#_S_size

试着按照文本中的建议添加一个计数字段。

18

这不是一个完美的解决方案,但你可以使用原始的 Mongo 查询和 $where 操作符,举个例子:

posts = Post.objects.filter(__raw__={'$where': 'this.likes.length > 20'})

另一种选择是检查第21个元素是否存在,这种方法应该会更快,但我觉得不太清晰:

posts = Post.objects.filter(likes__21__exists=True)

第二种选择只有在你使用 MongoDB 2.2 及以上版本时才有效。

来源:摘自这些 回答,并应用于 MongoEngine。

撰写回答