首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用ReferenceField()的MongoEngine条件过滤器

使用ReferenceField()的MongoEngine条件过滤器
EN

Stack Overflow用户
提问于 2019-03-27 11:35:10
回答 1查看 883关注 0票数 2

假设有简单的UserPost模型。

代码语言:javascript
复制
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)

结果为

john post测试帖子管理员帖子

我触发了条件user__ne=hide,所以除了hide的帖子之外,所有的帖子都会打印出来。

在这种情况下,我如何添加更多的条件likes,gender='W'?

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

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

代码语言:javascript
复制
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的错误

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

代码语言:javascript
复制
gender = User.objects(gender__ne='M')
posts = Post.objects(Q(user__ne=hide) & Q(user__nin=gender))

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

问题

  1. 是否可以一次使用条件查询?
  2. Do .objects()实际查询数据库?
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-05 03:14:47

如同级github ticket中的详细信息

1- mongodb中没有连接,因此除了您建议的连接之外,没有其他选择。要提高性能并减少内存占用,您可以做的一件简单的事情就是只获取用户is,如下所示:

代码语言:javascript
复制
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))

注意:在mongoengine中有一个CachedReferenceField,它可以帮助你实现你想要的东西(它基本上会在帖子集合中的用户引用旁边复制gender的值)并保持同步,但是CachedReferenceField有一些but (以及保持它们同步的性能问题),所以也许它可以在简单的用例中做到这一点,但我不建议使用它。

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

代码语言:javascript
复制
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
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55369396

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档