【问题标题】:mongoengine - query how to filter by ListField sizemongoengine - 查询如何按 ListField 大小进行过滤
【发布时间】:2013-02-07 10:29:02
【问题描述】:

我有以下型号:

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) 

评论?

【问题讨论】:

    标签: python mongodb mongoengine mongodb-query


    【解决方案1】:

    远非完美的解决方案,但您可以使用原始 mongo 查询和 $where 运算符,例如:

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

    另一个应该更快,但在我看来不太清楚的选项是检查第 21 个元素是否存在:

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

    第二个选项仅在您使用 MongoDB 2.2+ 时才有效

    来源:取自这些answers 并应用于MongoEngine。

    【讨论】:

    • 这是一个很好的技巧。谢了。我很好奇在服务器端使用“长度”是否不会很昂贵。
    • 是的,它有点贵。您基本上是在评估每个文档的函数(在本例中为 length > 20)。 exists 版本应该效率更高...
    【解决方案2】:

    您不能将 $size 用于值范围。

    来自 mongo 的网站:

    $size 不接受值范围。根据不同的字段选择文档 元素数量,创建一个计数器字段,当您将元素添加到字段时会增加该字段。

    这是导致答案的相关问题的链接:remove documents with array field's size less than 3 in mongoDB

    这是上一个链接链接到的 mongo 页面,该页面提供了上面块中的文档: http://docs.mongodb.org/manual/reference/operator/size/#_S_size

    尝试按照文本块中的建议添加计数器字段。

    【讨论】:

    • 谢谢。不知道有没有计划实现这个功能?
    • 即将发布的发行说明中没有任何内容表明会发生变化,但我对 2.2.4 版本之后的开发没有任何了解。我想原因与 $size 是如何在幕后实现的具体有关,他们实际上并没有这样做,但我从来没有看过,所以我不知道。
    猜你喜欢
    • 2019-04-22
    • 1970-01-01
    • 2012-02-21
    • 1970-01-01
    • 2016-05-18
    • 1970-01-01
    • 2018-01-31
    • 1970-01-01
    相关资源
    最近更新 更多