20

我正在使用 python 的 mongoengine 来查询 MongoDB,并且大部分时间都喜欢它,但是我遇到了高级查询的问题。

这是我的模型

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 where if eitherpublic或 the creatorbut not both。这是预期的吗?

我忽略了什么吗?我应该直接用 mongodb 而不是 mongoengine 来做这个吗?

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

4

5 回答 5

10

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

于 2019-05-31T20:10:58.113 回答
6

在这种情况下,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')
于 2011-11-21T21:34:41.957 回答
6

进行查询的正确方法是使用按位运算|以及&您在问题中编写它的方式:

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 文档中进行了解释。

于 2015-11-17T13:10:06.823 回答
2

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})
于 2015-04-17T19:09:21.043 回答
2

你可能导入了错误的 Q

from mongoengine.queryset.visitor import Q as mongo_Q

from django.db.models import Q as normal_Q
于 2017-11-28T15:07:53.380 回答