我有三个输入来自表单。它们是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
最佳答案
您要使用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。关于mysql - Django中的加权搜索,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3752812/