Как эффективно объединить оценку рекомендаций на основе Redis с набором запросов Django для постраничных каналов?

Я создаю приложение marketplace (например, раздел объявлений с переговорами) и пытаюсь внедрить персонализированную ленту рекомендаций. У меня возник вопрос по гибридной архитектуре, как лучше всего с этим справиться:

Текущая настройка:

  • Серверная часть Django с PostgreSQL для данных о продуктах
  • Redis для пользовательских предпочтений, действий и вычисленных оценок рекомендаций
  • Сельдерей для генерации справочных рекомендаций

Задача: Мне нужно предоставить постраничную ленту, в которой порядок определяется оценкой на основе Redis (пользовательские предпочтения, трендовые товары, активность при согласовании), но фактические данные о продукте происходит от моделей Django.

Мой нынешний подход:

  1. Задача Celery генерирует упорядоченный список идентификаторов продуктов на основе показателей Redis
  2. Кэшируйте этот упорядоченный список в Redis (например,, [123, 456, 789, ...])
  3. Для каждого запроса страницы вырезайте кэшированный список идентификаторов
  4. Используйте Case/When в Django для поддержания порядка, определенного в Redis:
preserved_order = models.Case(
    *[models.When(pk=pk, then=pos) for pos, pk in enumerate(page_product_ids)],
    output_field=models.IntegerField()
)

products = Product.objects.select_related('seller').filter(
    id__in=page_product_ids
).annotate(preserved_order=preserved_order).order_by('preserved_order')

Вопросы:

  1. Является ли использование Case/When с enumerate() наиболее эффективным способом сохранения порядка, определенного Redis, в Django?
  2. Должен ли я кэшировать фактические данные о продукте в Redis, а не только идентификаторы?
  3. Есть какие-нибудь лучшие шаблоны для этой комбинации данных Redis scoring + Django?
  4. Как вы решаете проблему "холодного запуска", когда рекомендации еще не готовы?

Фид должен обрабатывать ~10 тыс. продуктов с обновлением результатов в режиме реального времени. Мы будем признательны за любые советы по архитектуре или альтернативные подходы!

Технический стек: Django 4.2, Redis, Celery, PostgreSQL

Задача: мне нужно создать постраничную ленту, порядок в которой определяется оценкой на основе Redis

В этом случае мы, таким образом, знаем, какие элементы будут на странице. Итак, что вы можете сделать, это сначала разбиить на страницы список идентификаторов для извлечения, например:

from django.core.paginator import Paginator

page_product_ids = [123, 456, 789]

paginator = Paginator(page_product_ids, 2)
page = paginator.page(1)  # or any other page

preserved_order = models.Case(
    *[models.When(pk=pk, then=pos) for pos, pk in enumerate(page.object_list)],
    output_field=models.IntegerField()
)

products = (
    Product.objects.select_related('seller')
    .filter(id__in=page.object_list)
    .order_by(preserved_order.asc())
)

и теперь products уже разбит на страницы, учитывая, что все эти идентификаторы, таким образом, все еще существуют в базе данных. Если вы не уверены.

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