У меня есть три входа, поступающих из формы. Это name
, neighborhoods
и tags
. Окрестности и теги - это многострочные списки строк. Вот мой текущий запрос:Взвешенный поиск в Django
q = Restaurant.objects.filter(name__icontains=name)
q = q.filter(neighborhoods__name__in=neighborhoods)
for tag in tags:
q = q.filter(tags__name=tag)
q = q.order_by('name').distinct()
который в настоящее время получает все рестораны, которые имеют все теги и все из окрестностей. У меня есть небольшая проблема, сделав это взвешенным поиском. В принципе, для каждого совпадающего тега и окрестности я хочу добавить точку в столбец веса. Затем я закажу по весу, и даже если ресторан будет соответствовать только двум из трех тегов, он будет показываться (его вес будет 2). Это делается для того, чтобы не допустить 0 результатов и показать, насколько это возможно. Кроме того, я хочу, чтобы для выбора ресторана требовалось не менее 1 балла.
Я думаю, в SQL было бы что-то вроде:
SELECT *,
(SELECT COUNT(1)
FROM tags t
WHERE t.name IN (%s)
) AS weight
FROM restaurants
WHERE weight > 0
ORDER BY weight DESC
Подождите минуту здесь ... это просто подсчет количества тегов для ресторана, а не # тегов, соответствующих списку тегов. Мне нужно что-то вроде '.annotate (num_tags = Count ('tags__name__in' = tags)) –
Нет, код' q = q.filter (tags__name__in = tags) 'ограничивает строки только тегами, которые соответствуют. '.annotate (Count ('tags__name'))' группирует записи по всем, кроме записи тега. Если вы ищете 5 тегов, у вас есть 3 ресторана, A, B и C; и A соответствует 1 тегу, B 3 и C 4, а затем после аннотированных строк (A: num_tags 1, B: num_tags 3, C: num_tags 4) и 'filter()' удаляет A, оставляя B и C. Я могу скажите, что '.annotate (num_tags = Count ('tags__name__in' = tags))' будет выдавать ошибку. Аргумент для 'Count' - это просто имя поля, а не предложение, как в фильтре. –
ОК, мой плохой. Спасибо огромное! –