我有三个来自表单的输入。它们是name
,neighborhoods
和tags
。邻域和标签是多选框字符串列表。这是我目前的查询:
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
答案 0 :(得分:2)
您想使用annotate()
from django.db.models import Count
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').annotate(num_tags=Count('tags__name')).filter(num_tags__gte=2)
<强>更新强>
再次查看代码,我发现不幸的是它会被过滤掉,以便只与所有标签匹配。我认为这种改变应该有效:
摆脱:
for tag in tags:
q = q.filter(tags__name=tag)
替换为:
q = q.filter(tags__name__in=tags)
这样,它匹配餐馆被标记至少一个所请求标签的所有查询。稍后annotate
和filter
会确保匹配至少2个。