mirror of
https://github.com/jazzband/django-ddp.git
synced 2026-03-16 22:40:24 +00:00
Make the SQL for subscriptions much faster to run.
The PostgreSQL query planner knows to short-circuit some operators such as IN or ANY such that `foo_id IN (SELECT foo.id FROM foo WHERE ...)` doesn't need to perform a full table scan on foo. This change ensures that `user_rel` WHERE clauses use the `IN` operator to take advantage of the greatly improved performance.
This commit is contained in:
parent
07fcf39e0a
commit
80238bc785
1 changed files with 18 additions and 1 deletions
19
dddp/api.py
19
dddp/api.py
|
|
@ -279,8 +279,25 @@ class Collection(APIMixin):
|
|||
if isinstance(user_rels, basestring):
|
||||
user_rels = [user_rels]
|
||||
user_filter = None
|
||||
# Django supports model._meta -> pylint: disable=W0212
|
||||
meta = self.model._meta
|
||||
for user_rel in user_rels:
|
||||
filter_obj = Q(**{user_rel: user})
|
||||
name, rel = (user_rel.split('__', 1) + [None])[:2]
|
||||
field = meta.pk if name == 'pk' else meta.get_field(name)
|
||||
# generate `filter_obj` (instance of django.db.models.Q)
|
||||
if field not in meta.local_fields:
|
||||
# user_rel spans a join - ensure efficient SQL is generated
|
||||
# such as `...WHERE foo_id IN (SELECT foo.id FROM ...)`
|
||||
# rather than creating an explosion of INNER JOINS.
|
||||
filter_obj = Q(**{
|
||||
'%s__in' % name: field.related_model.objects.filter(
|
||||
**{rel or 'pk': user}
|
||||
).values('pk'),
|
||||
})
|
||||
else:
|
||||
# user rel is a local field -> no joins to avoid.
|
||||
filter_obj = Q(**{str(user_rel): user})
|
||||
# merge `filter_obj` into `user_filter`
|
||||
if user_filter is None:
|
||||
user_filter = filter_obj
|
||||
else:
|
||||
|
|
|
|||
Loading…
Reference in a new issue