在mongoengine中使用MongoDB的OR条件

21 投票
5 回答
18139 浏览
提问于 2025-04-17 06:37

我正在使用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 布尔运算符 andor不行的。这一点在 MongoEngine 的文档中有解释。

13

MongoEngine的文档说的不是这样。请查看这个链接:

MongoEngine查询文档

http://docs.mongoengine.org/guide/querying.html

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

撰写回答