我有三个输入来自表单。它们是nameneighborhoodstags。邻居和标签是多选框字符串列表。这是我当前的查询:

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)


这样,它会匹配所有用至少一个请求的标签标记了饭店的查询。后面的annotatefilter确保至少匹配2。

关于mysql - Django中的加权搜索,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3752812/

10-11 04:45