【问题标题】:MongoDB using an OR clause in mongoengineMongoDB 在 mongoengine 中使用 OR 子句
【发布时间】:2012-01-01 15:31:28
【问题描述】:

我正在使用 python 的 mongoengine 来查询 MongoDB,并且很喜欢它,但我遇到了 advanced query 的问题。

这是我的模型

class ContentItem(Document):
    account = ReferenceField(Account)
    creator = ReferenceField(User)
    public = BooleanField(default=False) 
    last_used = DateTimeField(default=datetime.now)

我想查询属于特定帐户的所有ContentItem,这些帐户要么由登录用户创建,要么是公开的。这是我写的查询

query = ContentItem.objects.filter( (Q(account=account) & Q(public=True)) |  (Q(account=account) & Q(creator=logged_in_user)) ).order_by('-last_used')

或:

query = ContentItem.objects.filter( Q(account=account) & ( Q(public=True) |  Q(creator=logged_in_user) ) ).order_by('-last_used')

但这些似乎是 XOR,如果是 publiccreator,但不是两者兼而有之。这是预期的吗?

我是否忽略了什么?我应该直接使用 mongodb 而不是 mongoengine 来执行此操作吗?

我目前的解决方法是进行两个不同的查询并合并结果,但随着内容项目的数量变大,结果需要很长时间才能返回,因为我需要先获取所有项目才能订购它们,因此失去(django)分页结果的所有好处。

【问题讨论】:

    标签: python mongodb mongoengine


    【解决方案1】:

    MongoEngine 文档另有说明。请检查:

    【讨论】:

    • 这里是Mongoengine的维护者,接受的答案是错误的,这是正确的答案
    【解决方案2】:

    在这种情况下,mongoengine 文档显然是不正确的。不要使用按位运算符“&”和“|”,而应使用标准运算符“and”和“or”。

    所以你的第一个查询变成:

    query = ContentItem.objects.filter( (Q(account=account) and Q(public=True)) or  (Q(account=account) and Q(creator=logged_in_user)) ).order_by('-last_used')
    

    【讨论】:

    • 成功了。我在 github 帐户上添加了一个注释以修复文档 github.com/hmarr/mongoengine/issues/363
    • 不是这样的;请参阅上面引用的 github 问题。我试过这个,但使用 or 而不是 | 不会应用过滤器。使用 &| 对我来说效果很好。
    • @Paul - 也许你没有注意到这篇文章已经有 9 个月了,而且这个错误已经被修复了?
    • @apiguy 不。你一开始就错了。在 Python 中无法覆盖 and/or,而是可以覆盖 |/&。 Q 的源代码(mongoengine/queryset/visitor.py)及其历史证实了这一点
    • 您必须使用位运算符。您不能使用 or 来组合查询,因为 Q(a=a) 或 Q(b=b) 与 Q(a=a) | 不同。 Q(b=b)。由于 Q(a=a) 等于真 Q(a=a) 或 Q(b=b) 与 Q(a=a) 相同。文档 -> mongoengine-odm.readthedocs.org/guide/…
    【解决方案3】:

    进行查询的正确方法是使用按位运算|&,就像您在问题中所写的那样:

    query = ContentItem.objects.filter( (Q(account=account) & Q(public=True)) |  (Q(account=account) & Q(creator=logged_in_user)) ).order_by('-last_used')
    

    注意:使用标准 Python 布尔运算符 andor工作。这在MongoEngine documentation 中有解释。

    【讨论】:

      【解决方案4】:

      你可能导入了错误的 Q

      from mongoengine.queryset.visitor import Q as mongo_Q
      
      from django.db.models import Q as normal_Q
      

      【讨论】:

        【解决方案5】:

        https://github.com/MongoEngine/mongoengine/blob/master/tests/queryset/transform.py

        从第 134 行开始:

        def test_raw_query_and_Q_objects(self):
            query = Foo.objects(__raw__={'$nor': [{'name': 'bar'}]})._query
            self.assertEqual(query, {'$nor': [{'name': 'bar'}]})
        
            q1 = {'$or': [{'a': 1}, {'b': 1}]}
            query = Foo.objects(Q(__raw__=q1) & Q(c=1))._query
            self.assertEqual(query, {'$or': [{'a': 1}, {'b': 1}], 'c': 1})
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-06-02
          • 1970-01-01
          • 1970-01-01
          • 2016-08-13
          • 1970-01-01
          • 2017-09-26
          • 2011-08-23
          • 1970-01-01
          相关资源
          最近更新 更多