添加Django的Q()对象并获得两个互斥的JOIN ON [英] ADDing Django's Q() objects and get two exclusive JOIN ONs
问题描述
这是场景:
class Person(models.Model):
...
class Aktion(models.Model):
...
class Aktionsteilnahme(models.Model):
person = models.ForeignKey(Person)
aktion = models.ForeignKey(Aktion)
现在的问题是,我正在基于Q()
对象动态构建相当复杂的查询.他们最终像这样:
The problem now is, that I'm dynamically constructing rather complex queries based on Q()
-objects. They end up like this:
Person.objects.filter(
Q((Q()|Q(aktionsteilnahme__aktion=302))&
(Q()|Q(aktionsteilnahme__aktion=547)))
)
可以(并自动)减少为:
which can (and automatically will) be reduced to:
Person.objects.filter(
Q(aktionsteilnahme__aktion=302)&
Q(aktionsteilnahme__aktion=547)
)
问题现在是,这会导致如下所示的SQL:
The problem now is, that this results in a SQL like this:
SELECT * FROM person
LEFT OUTER JOIN aktionsteilnahme ON ( person.id = aktionsteilnahme.person_id )
WHERE (aktionsteilnahme.aktion = 2890 AND aktionsteilnahme.aktion = 5924)
但是我实际需要的是:
Person.objects.filter(Q(aktionsteilnahme__aktion=302))
.filter(Q(aktionsteilnahme__aktion=547))
导致我实际需要的东西:
resulting in what I would actually need:
SELECT * FROM person
INNER JOIN aktionsteilnahme ON ( person.id = aktionsteilnahme.person_id )
INNER JOIN aktionsteilnahme T4 ON ( person.id = T4.person_id )
WHERE (aktionsteilnahme.aktion = 302 AND T4.aktion = 547)
我无法使用建议的解决方案,因为所有这些都将再次被OR
编辑.
I can't use the proposed solution though because all of it is gonna be OR
'ed again.
我必须能够做类似的事情:
I would have to be able to do something like:
Person.objects.filter(
Q(
Q(aktionsteilnahme__aktion=302))
.filter(Q(aktionsteilnahme__aktion=547))
)
|
Q(other_q_filters)
)
推荐答案
经过进一步的修改后,我意识到:Django QuerySets可以进行OR
编辑.
After fiddling some more I realized: Django QuerySets can be OR
'ed.
因此,我的解决方案是现在创建类似这样的内容:
My solution therefore is now to create something like this:
Person.objects.filter(Q(aktionsteilnahme__aktion=302))
.filter(Q(aktionsteilnahme__aktion=547))
|
Person.objects.filter(Q(other_q_filters))
现在,所有内部AND
都使用过滤器进行连接,而最外部的OR
则是直接在QuerySet上的布尔值|
.
All the inner AND
s are now concatenated using filters, and the outer-most OR
s are boolean |
directly on the QuerySets.
注意! 由于内部子查询总是被完全评估(不再有限制20"),因此请求变得慢得多.
和
OR
-ing QuerySets将导致多个条目-所以最后一个
Heads up! Requests get much slower due to inner subqueries always being completely evaluated (no more "limit 20")
and
OR
-ing QuerySets will result in multiple entries - so a final
(QuerySet | QuerySet | QuerySet).distinct()
通常是必需的.
这篇关于添加Django的Q()对象并获得两个互斥的JOIN ON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!