下面是我想要实现的逻辑:
我使用Elasticsearch显示最畅销的产品,并使用function_score
查询DSL在结果中随机插入新创建的产品。
我面临的问题是,对于新创建的产品,我使用的是random_score
fn,查询会插入新产品,直到第2或3页为止,但是在搜索结果结束时,所有其他新创建的产品都会停止使用。
下面是为function_score
编写的逻辑
function_score: {
query: query,
functions: [
{
filter: [
{ terms: { product_type: 'sponsored') } },
{ range: { live_at: { gte: 'CURRENT_DATE - 1.MONTH' } } }
],
random_score: {
seed: Time.current.to_i / (60 * 10), # new seed every 10 minutes
field: '_seq_no'
},
weight: 0.975
},
{
filter: { range: { live_at: { lt: 'CURRENT_DATE - 1.MONTH' } } },
linear: {
weighted_sales_rate: {
decay: 0.9,
origin: 0.5520974289580515,
scale: 0.5520974289580515
}
},
weight: 1
}
],
score_mode: 'sum',
boost_mode: 'replace'
}
然后我将基于{"_score" => { "order" => "desc" } }
进行排序
假设在过去的一个月里有100种赞助产品被创造出来。然后,当我滚动2或3页时,上面的Elasticsearch查询显示8-10个随机产品(每页3到4个),但是在结果的最后几页中显示所有其他90-92产品。-这是因为random_score
计算出的90-92产品的分数比用linear
衰减函数计算的分数低。
请建议如何修改此查询,以便在浏览页面时继续查看新创建的产品,并防止在结果结束时推送新记录。
更新
我尝试在这个查询中添加gauss
衰变函数(这样我就可以以某种方式修改接近结果末尾的产品的分数),如下所示:
{
filter: [
{ terms: { product_type: 'sponsored' } },
{ range: { live_at: { gte: 'CURRENT_DATE - 1.MONTH' } } },
{ range: { "_score" => { lt: 0.9 } } }
],
gauss: {
views_per_age_and_sales: {
origin: 1563.77,
scale: 1563.77,
decay: 0.95
}
},
weight: 0.95
}
但这也不起作用。
我所提到的链接:
发布于 2022-06-20 08:47:20
我不确定这是否是最好的解决方案,但我能够通过使用script_score
query +包装原始查询来完成这一任务,我添加了一个名为sort_by_views_per_year
的新的ElasticSearch索引。以下是解决方案的外观:
我提到的链接:https://github.com/elastic/elasticsearch/issues/7783
attribute(:sort_by_views_per_year) do
object.live_age&.positive? ? object.views_per_year.to_f / object.live_age : 0.0
end
然后在查询ElasticSearch时:
def search
#...preparation of query...#
query = original_query(query)
query = rearrange_low_scoring_docs(query)
sort = apply_sort opts[:sort]
Product.search(query: query, sort: sort)
end
我没有在original_query
中更改任何东西(即使用random_score
到products <= 1.month.ago
,然后使用linear
衰变函数)。
def rearrange_low_scoring_docs query
{
function_score: {
query: query,
functions: [
{
script_score: {
script: "if (_score.doubleValue() < 0.9) {return 0.9;} else {return _score;}"
}
}
],
#score_mode: 'sum',
boost_mode: 'replace'
}
}
end
最后,我的分类如下:
def apply_sort
[
{ '_score' => { 'order' => 'desc' } },
{ 'sort_by_views_per_year' => { 'order' => 'desc' } }
]
end
如果ElasticSearch random_score
查询DSL开始支持类似于:max_doc_to_include
和min_score
属性,这将是非常有帮助的。这样我就可以像:
{
filter: [
{ terms: { product_type: 'sponsored' } },
{ range: { live_at: { gte: 'CURRENT_DATE - 1.MONTH' } } }
],
random_score: {
seed: 123456, # new seed every 10 minutes
field: '_seq_no',
max_doc_to_include: 10,
min_score: 0.9
},
weight: 0.975
},
https://stackoverflow.com/questions/72622098
复制相似问题