Django可以做嵌套查询和排除吗
Posted
技术标签:
【中文标题】Django可以做嵌套查询和排除吗【英文标题】:Can Django do nested queries and exclusions 【发布时间】:2011-01-22 12:19:00 【问题描述】:我需要一些帮助来将这个查询放在 Django 中。我已将此处的示例简化为切入正题。
MyModel(models.Model):
created = models.DateTimeField()
user = models.ForeignKey(User)
data = models.BooleanField()
我想用英语创建的查询听起来像:
给我昨天创建的每条数据为假的记录,在同一范围内,给定用户的数据永远不会显示为真
这是一个输入/输出示例,以防不清楚。
表格值
ID Created User Data
1 1/1/2010 admin False
2 1/1/2010 joe True
3 1/1/2010 admin False
4 1/1/2010 joe False
5 1/2/2010 joe False
输出查询集
1 1/1/2010 admin False
3 1/1/2010 admin False
我要做的是排除记录#4。原因是在“昨天”的给定范围内,对于记录 #2 中的用户,数据显示为 True 一次,因此将排除记录 #4。
从某种意义上说,似乎发生了 2 个查询。一种用于确定给定范围内的记录,另一种用于排除与“真”记录相交的记录。
如何使用 Django ORM 进行此查询?
【问题讨论】:
【参考方案1】:您不需要嵌套查询。您可以生成不良用户的 PK 列表,然后在下一个查询中排除包含这些 PK 的记录。
bad = list(set(MyModel.obejcts.filter(data=True).values_list('user', flat=True)))
# list(set(list_object)) will remove duplicates
# not needed but might save the DB some work
rs = MyModel.objects.filter(datequery).exclude(user__pk__in=bad)
# might not need the pk in user__pk__in - try it
您可以将其浓缩为一行,但我认为这与您将得到的一样简洁。 2 个查询还不错。
编辑:您可能想阅读有关此的文档:
http://docs.djangoproject.com/en/dev/ref/models/querysets/#in
这听起来像是自动嵌套查询(因此只有一个查询会在数据库中触发),如果是这样的话:
bad = MyModel.objects.filter(data=True).values('pk')
rs = MyModel.objects.filter(datequery).exclude(user__pk__in=bad)
但是 mysql 并没有很好地优化这一点,所以我上面的代码(2 个完整查询)实际上最终可以运行得更快。
两者都试一试!
【讨论】:
非常酷。我将该模式适应了我的实际实现,并且效果很好。在此过程中,我还学到了一些巧妙的技巧。我认为__in
是我追求的主要秘密成分。【参考方案2】:
看起来你可以使用:
从 django.db.models 导入 F
MyModel.objects.filter(datequery).filter(data=False).filter(data = F('data'))
F
对象可从版本1.0
获得
请测试一下,我不确定。
【讨论】:
【参考方案3】:感谢惰性求值,您可以将查询分解为几个不同的变量,以使其更易于阅读。下面是一些 ./manage.py shell
的游戏时间,采用 Oli 已经呈现的风格。
> from django.db import connection
> connection.queries = []
> target_day_qs = MyModel.objects.filter(created='2010-1-1')
> bad_users = target_day_qs.filter(data=True).values('user')
> result = target_day_qs.exclude(user__in=bad_users)
> [r.id for r in result]
[1, 3]
> len(connection.queries)
1
如果你想在同一个查询中拉入用户对象,你也可以说result.select_related()
。
【讨论】:
以上是关于Django可以做嵌套查询和排除吗的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 findOne 查询 mongodb 并排除数组中的一些嵌套字段