控制搜索结果位置 SearchKick

controlling search results position SearchKick

我正在使用 SearchKick,这很棒,我是从一个非常糟糕的搜索实现中迁移过来的,在迁移到 SearchKick 并对我们的搜索进行大修之前,产品团队并没有给予我太多信任,他们让我添加了硬编码查询结果,所以他们可以说对于这个搜索输入我希望这个产品首先出现。现在我从数据库中获取回答某个请求查询的查询结果,并将它们添加到顶部(我不在乎你是否想要位置 48 的结果,如果有 4 个硬编码结果,它将是第 4 个).尽管如果可能的话,最好将它们放在中间。

使用 SearchKick 最干净的方法是什么,以便查询将在 elastic 内部进行(索引产品中的硬编码结果)

我有 2 个模型 Product 和 QueryResult,QueryResult 包含一个产品、一个查询字符串和一个 wanted_rank

在我的产品模型中,我确实有一种方法可以获取如下所示的搜索结果:

def get_search_results(query_string)
  # get search results from elastic using searchkick
  search_results = Product.search(query_string)
  
  # get hardcoded results matching this query
  hardcoded_results = QueryResults.where(query: query).order(:wanted_rank).map(&:product)
  
  # remove hardcoded results from search_results
  search_results = search_results - hardcoded_results

  # return results where hardcoded results are first
  hardcoded_results + search_results
end

最后我希望所有搜索逻辑都发生在 elastic 上,包括插入硬编码的搜索结果

因此,在一些非常有用的评论和更多搜索之后,我找到了解决方案。 首先,我的第一个错误是尝试使用 boosts 而不是 order 来修复它,为此我们将特定产品的所有 QueryResults 索引到名为 query_results 的字段下。 对于具有查询结果的产品 x:

{
  query: 'foo',
  wanted_rank: 1,
},
{
  query: 'bar',
  wanted_rank: 2,
}

我会索引:

{
  name: 'x',
  query_results: {
    'foo': 1,
    'bar': 2
  }
}

比搜索时,给定一个名为查询的属性,我会做如下:

Product.search(
  query,
  order: [ 
    { "query_results.#{query}": { unmapped_type: :long },
    { _score: :desc } 
  ]
)

2 件需要注意的重要事项:

  1. use unmapped_type 这将告诉 elastic 在没有映射时使用什么映射,每个没有查询结果的随机查询(这是大多数)将没有映射“query_results.#{query}" 因为它不会被索引,因此我们添加 unmapped_type 来告诉 elastic 如果你没有像它 long 那样的映射行为。
  2. 在搜索和保存数据库时,我都会将查询小写和删除,以便正确匹配。

我还对另一个字段下的查询进行索引,并以低权重对其进行搜索,以确保该产品会出现在该查询中。