Как эффективно объединить оценку рекомендаций на основе Redis с набором запросов Django для постраничных каналов?
Я создаю приложение marketplace (например, раздел объявлений с переговорами) и пытаюсь внедрить персонализированную ленту рекомендаций. У меня возник вопрос по гибридной архитектуре, как лучше всего с этим справиться:
Текущая настройка:
- Серверная часть Django с PostgreSQL для данных о продуктах
- Redis для пользовательских предпочтений, действий и вычисленных оценок рекомендаций
- Сельдерей для генерации справочных рекомендаций
Задача: Мне нужно предоставить постраничную ленту, в которой порядок определяется оценкой на основе Redis (пользовательские предпочтения, трендовые товары, активность при согласовании), но фактические данные о продукте происходит от моделей Django.
Мой нынешний подход:
- Задача Celery генерирует упорядоченный список идентификаторов продуктов на основе показателей Redis
- Кэшируйте этот упорядоченный список в Redis (например,,
[123, 456, 789, ...]) - Для каждого запроса страницы вырезайте кэшированный список идентификаторов
- Используйте
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')
Вопросы:
- Является ли использование
Case/Whenсenumerate()наиболее эффективным способом сохранения порядка, определенного Redis, в Django? - Должен ли я кэшировать фактические данные о продукте в Redis, а не только идентификаторы?
- Есть какие-нибудь лучшие шаблоны для этой комбинации данных Redis scoring + Django?
- Как вы решаете проблему "холодного запуска", когда рекомендации еще не готовы?
Фид должен обрабатывать ~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 уже разбит на страницы, учитывая, что все эти идентификаторы, таким образом, все еще существуют в базе данных. Если вы не уверены.