控制搜索结果位置 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 件需要注意的重要事项:
- use unmapped_type 这将告诉 elastic 在没有映射时使用什么映射,每个没有查询结果的随机查询(这是大多数)将没有映射“query_results.#{query}" 因为它不会被索引,因此我们添加 unmapped_type 来告诉 elastic 如果你没有像它 long 那样的映射行为。
- 在搜索和保存数据库时,我都会将查询小写和删除,以便正确匹配。
我还对另一个字段下的查询进行索引,并以低权重对其进行搜索,以确保该产品会出现在该查询中。
我正在使用 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 件需要注意的重要事项:
- use unmapped_type 这将告诉 elastic 在没有映射时使用什么映射,每个没有查询结果的随机查询(这是大多数)将没有映射“query_results.#{query}" 因为它不会被索引,因此我们添加 unmapped_type 来告诉 elastic 如果你没有像它 long 那样的映射行为。
- 在搜索和保存数据库时,我都会将查询小写和删除,以便正确匹配。
我还对另一个字段下的查询进行索引,并以低权重对其进行搜索,以确保该产品会出现在该查询中。