代码之家  ›  专栏  ›  技术社区  ›  Matt Williamson

Django中的加权搜索

  •  0
  • Matt Williamson  · 技术社区  · 14 年前

    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
    
    1 回复  |  直到 14 年前
        1
  •  2
  •   Jordan Reiter    14 年前

    你想用 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个。