Эффективные запросы в django Query

Мы работаем над созданием газеты с помощью django. Прежде чем читать дальше, позвольте мне показать вам код.

    # Fetch lead, top, and other filtered news
    news_objects = news.objects.filter(website=host, is_published__in=[True], published_date__lt=current_datetime).only('Category','title','news_brief','image','img_caption','published_date','news_id')
    lead = news_objects.filter(status='lead').order_by('-published_date').first()
    top = news_objects.filter(status='top').order_by('-published_date')[:4]
    filtered_news = news_objects.exclude(status__in=['lead', 'top']).order_by('-published_date')

    # Fetch filtered categories and prefetch limited news related to filtered categories
    categories_with_news = catagory.objects.filter(website=host, show_front__in=[True]).prefetch_related(
        Prefetch('catagory', queryset=filtered_news, to_attr='limited_news')
    )

    # Limit the news to the first 5 for each category
    for category in categories_with_news:
        category.limited_news = category.limited_news[:6]`

Нижеприведенный код будет собирать все новости в определенном домене. Новости содержат более 10k

news_objects = news.objects.filter(website=host, is_published__in=[True], published_date__lt=current_datetime).only('Category','title','news_brief','image','img_caption','published_date','news_id')

Нижеприведенный код получит только 5 новостей из news_objects


lead = news_objects.filter(status='lead').order_by('-published_date').first()
top = news_objects.filter(status='top').order_by('-published_date')[:4]

Ниже приведен код, который получит все категории, которые будут отображаться впереди вместе с их данными.

categories_with_news = catagory.objects.filter(website=host, show_front__in=[True]).prefetch_related(
        Prefetch('catagory', queryset=filtered_news, to_attr='limited_news')
    )

Помимо этого, приведенный ниже код будет получать 6 новостей для каждой категории.

for category in categories_with_news:
        category.limited_news = category.limited_news[:6]

Здесь моя проблема в том, что я не думаю, что это хорошая идея, чтобы получить все новости, потому что мне нужно не более 60 новостей. Как сделать это эффективно.

Я попробовал ограничить запрос до 300, но и тут возникла проблема, возможно, в какой-то категории №6 может находиться на 350 позиции.

Несколько вещей:

  1. не итерируйте categies_with_news, устанавливайте ограничения, когда это действительно необходимо (например, время сериализации/ответа).
  2. не используйте __in=[True], вместо этого используйте =True.
  3. убедитесь, что вы индексируете status published_date website
  4. Убедитесь, что ваши ответы постранично оформлены.

#1 - ваш главный убийца.

для такого запроса с <10 миллионами записей время ответа должно составлять около .2 +-.1 с или около того.

Как часто появляются новые новости? Я предполагаю, что извлечение новостей - гораздо более частая операция, чем добавление новых новостей. Поэтому добавьте немного больше работы к менее частой операции. В общем, храните в БД некоторую дополнительную информацию, которая меняется довольно редко, чтобы ускорить запросы на поиск.

Вы можете поддерживать флаг top_six для своих новостных объектов. Каждый раз, когда добавляется новая новость, получайте текущую шестерку лучших в категории new_new, снимайте флаг для той, которая больше не входит в шестерку из-за нового добавления, и добавляйте новую с установленным флагом. Вероятно, вам также нужно выполнять ежечасную? ежедневную? операцию, чтобы взять все top_six и снять флаг с тех, которые слишком устарели (или, может быть, непопулярны?), чтобы сохранить статус.

Получение текущей шестерки лучших для некоторых или всех категорий будет фильтроваться по этому флагу. В этом случае вам не придется перебирать категории с новостями или срезами для их извлечения. Вы никогда не получите более шести новостей в любой категории, но один запрос к БД может получить новости по всем или нескольким (__in) категориям.

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