mongodb - MongoEngine 使用 ReferenceField() 进行条件过滤

标签 mongodb mongoengine

假设有简单的UserPost模型。

class User(Document):
    user_id = StringField(primary_key=True)
    gender = StringField(default='M')


class Post(Document):
    user = ReferenceField(User)
    body = StringField()


if __name__ == '__main__':
    hide = User(user_id='hide', gender='M').save()
    john = User(user_id='john', gender='M').save()
    test = User(user_id='test', gender='W').save()
    admin = User(user_id='admin', gender='W').save()

    Post(user=hide, body='hide post').save()
    Post(user=john, body='john post').save()
    Post(user=test, body='test post').save()
    Post(user=admin, body='admin post').save()

    hide = User.objects(user_id='hide').first()

    posts = Post.objects(user__ne=hide)
    for post in posts:
        print(post.body)

结果是

约翰·波斯特 测试帖 管理员帖子

我触发了条件 user__ne=hide,因此除了 hide 的帖子之外的所有帖子都被打印。

在这种情况下,如何添加更多条件,例如,性别='W'?

下面的代码是我尝试的结果。

posts = Post.objects(user__ne=hide, user__gender__ne='M')

from mongoengine.queryset.visitor import Q

posts = Post.objects(Q(user__ne=hide) & Q(user__gender__ne='M'))

但这两个代码都会抛出错误 -> mongoengine.errors.InvalidQueryError: Cannot Perform join in mongoDB: user__gender

我知道可以用这个来实现。

gender = User.objects(gender__ne='M')
posts = Post.objects(Q(user__ne=hide) & Q(user__nin=gender))

但是如果用户的行数过多,则可能会出现内存问题。

问题

  1. 是否可以一次性带条件查询?

  2. .objects() 是否实际查询数据库?

最佳答案

如 sibling github ticket 的详细信息

1 - mongodb 中没有联接,因此除了您建议的选项之外没有其他选项。为了提高性能和减少内存占用,您可以做的一件简单的事情就是仅获取用户 ID,请参见下文:

male_ids = User.objects(gender__ne='M').scalar('id')   # Only fetch the user ids, i.o loading full object data into User model
posts = Post.objects(Q(user__ne=hide) & Q(user__nin=male_ids))

注意:有一个 CachedReferenceField在 mongoengine 中,这可能会帮助您实现您想要的目标(它基本上会复制 Post 集合中对用户的引用旁边的 gender 值)并保持同步,但 CachedReferenceField 遇到一些错误(以及保持它们同步的性能问题)所以也许它可以解决简单的用例,但我不建议使用它。

2 - .objects() 返回一个查询集,仅当您迭代查询集(或打印查询集)时才会触发查询。见下文:

user_qs = User.objects()
print(type(user_qs))    # <class mongoengine.queryset.queryset.QuerySet>, query not fired yet
for user in qs_user:    # fires the actual query and load data in User instances
        pass

关于mongodb - MongoEngine 使用 ReferenceField() 进行条件过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55369396/

相关文章:

c# - 如何在 `RoleEntryPoint.OnStop()` 方法中优雅地关闭 mongod

Java 向 MongoDB 中的数组插入值

python - 在mongoengine中查询列表;包含与在

python - 如何使用 Marshmallow 序列化 MongoDB ObjectId?

python - 如何在mongoengine stringfield中返回选择值

mongodb - 如何在 MongoEngine 中按 id 从列表(ListField)中删除项目?

mongodb - 基于mongodb的$lookup中的$sort的结果

java - 如果从包含多个主机但不是副本集选项的 URI 创建 MongoClientURI 会发生什么?

java - Eclipse 和 mongodb 库中的 Maven Java 项目

python - 填充在 Mongoengine 中,引用字段