Проблему немного сложно объяснить, но я сделаю все возможное.Я создаю сервер GraphQL в Django (используя Graphene), и отчасти это необходимо для пакетной обработки запросов к базе данных, чтобы избежать проблем n + 1.Это означает, что, скажем, при выборке набора событий, а не по одному запросу для каждого идентификатора события, мы делаем один запрос с where id in (...)
.
. Я пытаюсь добиться того же с помощью списков.Мой непосредственный вариант использования - у каждого события есть место проведения, и я хочу получить следующие 5 (это произвольно) событий для каждого места только одним запросом.
(Примечание: для полного обоснования этого, Я недавно написал статью )
Запрос PostgreSQL, который я придумал, таков:
SELECT
*
FROM (
SELECT
*,
ROW_NUMBER()
OVER (PARTITION BY
venue_id
ORDER BY
starts_at,
ends_at,
id) AS row_index
FROM
events_event
WHERE
starts_at >= '2018-05-20') x
WHERE
row_index <= 5
Я не думаю Мне понадобятся описания дел, потому что я не думаю, что существует реальная необходимость иметь возможность группировать последующие страницы - только начальные.
Так что у меня есть несколько вопросовоб этом:
Есть ли лучший способ написания этого запроса?
Это предпочтительнее, чем запускать несколько (реально между 10 и 30) параллельно выполняет запросы, чтобы сделать это обычным способом?
Как мне выполнить этот запрос с помощью ORM Django (без перехода на сырой SQL)?
Третий вопрос - тот, над которым я бьюсь головой, потому что ORM кажется прОвидим все необходимые строительные блоки (я использую Django 2.0), но я не могу понять, как собрать их все вместе.
Это то, что я до сих пор использую Django:
Event.objects.annotate(
row_number=Window(
expression=RowNumber(),
partition_by=[F('venue_id')],
order_by=[F('starts_at').asc(), F('ends_at').asc(), F('id').asc()]
)
)
Но мне не удалось найти способ фильтрации по row_number, потому что я не хочу возвращать все - только первые 5. Когда я пытаюсь сделать следующее, Django говорит мне, что фильтрация не разрешенаОконные пункты:
Event.objects.annotate(
row_number=Window(
expression=RowNumber(),
partition_by=[F('venue_id')],
order_by=[F('starts_at').asc(), F('ends_at').asc(), F('id').asc()]
)
).filter(row_number__lte=5)