Можно ли получить N количество записей на значение в объединенной таблице БЕЗ многократных запросов?

Итак, у меня есть три таблицы:

article_page - (для моих статей) представлен моделью Page

article_page_category - склеивание таблицы между article_page и article_category, так как они многие ко многим

article_category - информация о категории, представленная моделью Category

Я хочу сделать запрос к базе данных, который получает N количество записей (возможно от 10 до 20) ПЕРВОЙ категории, желательно в одном запросе, так как у меня может быть много категорий одновременно, а это может быть довольно дорого.

Я пробовал всевозможные типы запросов и мне не везет - я даже пробовал различные подзапросы, но это не очень хорошо переводится на Django, а сырые sql-запросы трудно заставить работать.

Приведем пример:

Допустим, у меня есть категории бизнес, технологии, спорт

Я хочу получить 10 статей из бизнеса, 10 из технологий и 10 из спорта - все это категории в article_category

Есть ли способ сделать это с помощью одного запроса?

У меня сейчас есть что-то подобное, но я действительно думаю, что это неправильный подход:

class GroupedArticleListView(APIView):
    def get(self, request):
        categories = Category.objects.filter(taxon=1)
        categories = categories.annotate(
        top_articles=Subquery(
            Page.objects.filter(
                category=OuterRef("pk")
            ).order_by("-date").values_list("id", flat=True)[:10].first(),
            output_field=IntegerField()
            )
        )

База данных - MySQL, если это важно для ответа

Я понятия не имею, как перевести это в Django ORM, но лучший способ достичь этого - оконные функции (требуется MySQL 8.0):

SELECT *
FROM (
  SELECT ...,
    ROW_NUMBER() OVER (PARTITION BY ac.category_id ORDER BY a.date DESC) AS rownum
  FROM article_page AS a
  JOIN article_page_category AS ac ON a.id = ac.article_id
) AS t
WHERE rownum <= 10;

Я читал, что в Django 2.0 есть поддержка оконных функций, но я не являюсь пользователем Django, поэтому предоставлю вам возможность изучить этот вопрос. Смотрите, например, https://www.agiliq.com/blog/2017/12/django-20-window-expressions-tutorial/

Вернуться на верх