From e19d79a2bf9e3b177f3c59e01508aaf6fbc58745 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Tue, 18 May 2021 09:08:50 +0200 Subject: [PATCH] Orders API: optimize a common filter query --- doc/admin/indexes.rst | 2 ++ src/pretix/api/views/order.py | 27 ++++++++++++++------------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/doc/admin/indexes.rst b/doc/admin/indexes.rst index 668016374c..6a1823adec 100644 --- a/doc/admin/indexes.rst +++ b/doc/admin/indexes.rst @@ -45,6 +45,8 @@ Here is the currently recommended set of commands:: CREATE INDEX CONCURRENTLY pretix_addidx_order_comment ON pretixbase_order USING gin (upper("comment") gin_trgm_ops); + CREATE INDEX CONCURRENTLY pretix_addidx_order_event_date + ON public.pretixbase_order (event_id, datetime DESC); CREATE INDEX CONCURRENTLY pretix_addidx_orderpos_name ON pretixbase_orderposition USING gin (upper("attendee_name_cached") gin_trgm_ops); diff --git a/src/pretix/api/views/order.py b/src/pretix/api/views/order.py index db46cce36b..9ce5ac3dd8 100644 --- a/src/pretix/api/views/order.py +++ b/src/pretix/api/views/order.py @@ -27,7 +27,7 @@ from decimal import Decimal import django_filters import pytz from django.db import transaction -from django.db.models import Exists, F, OuterRef, Prefetch, Q +from django.db.models import Exists, F, OuterRef, Prefetch, Q, Subquery from django.db.models.functions import Coalesce, Concat from django.http import FileResponse, HttpResponse from django.shortcuts import get_object_or_404 @@ -97,30 +97,31 @@ with scopes_disabled(): model = Order fields = ['code', 'status', 'email', 'locale', 'testmode', 'require_approval'] + @scopes_disabled() def subevent_after_qs(self, qs, name, value): - qs = qs.annotate( - has_se_after=Exists( + qs = qs.filter( + pk__in=Subquery( OrderPosition.all.filter( subevent_id__in=SubEvent.objects.filter( - Q(date_to__gt=value) | Q(date_from__gt=value, date_to__isnull=True), event=OuterRef(OuterRef('event_id')) + Q(date_to__gt=value) | Q(date_from__gt=value, date_to__isnull=True), + event=self.request.event ).values_list('id'), - order_id=OuterRef('pk'), - ) + ).values_list('id') ) - ).filter(has_se_after=True) + ) return qs def subevent_before_qs(self, qs, name, value): - qs = qs.annotate( - has_se_before=Exists( + qs = qs.filter( + pk__in=Subquery( OrderPosition.all.filter( subevent_id__in=SubEvent.objects.filter( - Q(date_from__lt=value), event=OuterRef(OuterRef('event_id')) + Q(date_from__lt=value), + event=self.request.event ).values_list('id'), - order_id=OuterRef('pk'), - ) + ).values_list('id') ) - ).filter(has_se_before=True) + ) return qs def search_qs(self, qs, name, value):