在Django中加权搜索
问题描述:
我有三个输入从窗体进来。它们是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()
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)
更新
看代码,我再次看到,不幸的是它的过滤掉,以便只与所有标签匹配。我想,只是这种变化应该工作:
摆脱:
q = q.filter(tags__name__in=tags)
那它放在餐厅被加上的至少一个所有查询匹配方式:
for tag in tags:
q = q.filter(tags__name=tag)
与更换请求的标签。 annotate
和filter
后来负责确保它匹配至少2.
在这里等一下......这只是计算餐厅的标签数量,而不是与标签列表匹配的标签数量。我需要类似'.annotate(num_tags = Count('tags__name__in'= tags))' – 2010-09-20 17:06:14
不,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”的参数只是字段名称,而不是过滤器中的子句。 – 2010-09-20 18:43:47
好的,我的坏。非常感谢! – 2010-09-20 20:03:09