在mongoengine中使用MongoDB的OR条件
我正在使用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')
但是这些查询似乎是“异或”的意思,也就是说,要么是public
,要么是creator
,但不能同时满足两个条件。这是正常现象吗?
我是不是漏掉了什么?我是不是应该直接用mongodb,而不是mongoengine?
我现在的解决办法是做两个不同的查询,然后把结果合并,但随着内容项数量的增加,结果返回的时间变得很长,因为我需要先获取所有项才能进行排序,这样就失去了(django)分页结果的好处。
5 个回答
6
正确的查询方法是使用位运算符 |
和 &
,就像你在问题中写的那样:
query = ContentItem.objects.filter( (Q(account=account) & Q(public=True)) | (Q(account=account) & Q(creator=logged_in_user)) ).order_by('-last_used')
注意:使用标准的 Python 布尔运算符 and
和 or
是不行的。这一点在 MongoEngine 的文档中有解释。
13
5
在这个情况下,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')