MongoDB在mongoengine中使用OR子句

时间:2011-11-18 22:00:30

标签: python mongodb mongoengine

我正在使用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)分页结果的所有好处。

5 个答案:

答案 0 :(得分:8)

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

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

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')

答案 1 :(得分: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

中有解释

答案 2 :(得分:1)

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})

答案 3 :(得分:1)

你可能输错了Q

from mongoengine.queryset.visitor import Q as mongo_Q

from django.db.models import Q as normal_Q

答案 4 :(得分:1)

MongoEngine文档另有说明。请检查以下内容: http://docs.mongoengine.org/guide/querying.html