С одной стороны у меня есть база данных, обслуживающая огромный и сильно нормализованный ресурс. А с другой стороны, API, обслуживающий индивидуальные рекомендации для каждого элемента в этой базе данных.
Я хочу иметь возможность разбить список элементов на страницы, соответствующие критериям поиска и упорядоченные в зависимости от API рекомендаций. Например, если пользователь искал группы с типом Jazz, я бы хотел вернуть список всех упорядоченных соответствующих полос в зависимости от результатов нашего рекомендательного API. Наш API рекомендаций дает список всех групп с оценкой рекомендаций, которая уникальна для каждого пользователя.
Лучшее, что я могу придумать, - это получить страницу рекомендаций и выполнить запрос ORDER BY CASE
с каждой полосой упорядоченного отступления в результате рекомендации:
SELECT "band"."id"
FROM "band"
WHERE "band"."kind_id" = 42
ORDER BY CASE
WHEN ("band"."id" = 123) THEN 100
...
WHEN ("band"."id" = 456) THEN 1
ELSE 0
END DESC
LIMIT 100
В django этот же запрос выглядит так:
search = {"kind__name": "Jazz"}
recommendations = [
When(id=api_response["id"], then=Value(api_response["score"]))
for api_response in api_responses
]
queryset = (
Band.objects.annotate(
recommendations=Case(
*recommendations, default=Value(0), output_field=IntegerField(),
)
)
.filter(**search)
.order_by("-recommendations")[0:100]
)
Затем сделайте то же самое для следующей страницы до тех пор, пока я не верну все соответствующие полосы.
Но этот запрос не возвращает фиксированное количество полос на "страницу". В случае редкого вида это может привести к нескольким пустым страницам подряд. что будет медленным для пользователя.
Я использую Django и PostgreSQL для создания этого API, я бы не стал добавлять новые технологии, но мне интересно услышать какие-либо решения. (У меня уже есть настройка кластера Redis, поэтому я не возражаю против этого.)