首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Elasticsearch random_score将文档推入结果的末尾

Elasticsearch random_score将文档推入结果的末尾
EN

Stack Overflow用户
提问于 2022-06-14 18:58:05
回答 1查看 114关注 0票数 0

下面是我想要实现的逻辑:

我使用Elasticsearch显示最畅销的产品,并使用function_score查询DSL在结果中随机插入新创建的产品。

我面临的问题是,对于新创建的产品,我使用的是random_score fn,查询会插入新产品,直到第2或3页为止,但是在搜索结果结束时,所有其他新创建的产品都会停止使用。

下面是为function_score编写的逻辑

代码语言:javascript
运行
复制
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衰变函数(这样我就可以以某种方式修改接近结果末尾的产品的分数),如下所示:

代码语言:javascript
运行
复制
{
  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
}

但这也不起作用。

我所提到的链接:

  1. https://intellipaat.com/community/12391/how-to-get-3-random-search-results-in-elasticserch-query
  2. Query to get random n items from top 100 items in Elastic Search
  3. https://www.elastic.co/guide/en/elasticsearch/reference/7.17/query-dsl-function-score-query.html
EN

Stack Overflow用户

发布于 2022-06-20 08:47:20

我不确定这是否是最好的解决方案,但我能够通过使用script_score query +包装原始查询来完成这一任务,我添加了一个名为sort_by_views_per_year的新的ElasticSearch索引。以下是解决方案的外观:

我提到的链接:https://github.com/elastic/elasticsearch/issues/7783

代码语言:javascript
运行
复制
attribute(:sort_by_views_per_year) do
  object.live_age&.positive? ? object.views_per_year.to_f / object.live_age : 0.0
end

然后在查询ElasticSearch时:

代码语言:javascript
运行
复制
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_scoreproducts <= 1.month.ago,然后使用linear衰变函数)。

代码语言:javascript
运行
复制
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

最后,我的分类如下:

代码语言:javascript
运行
复制
def apply_sort
  [
    { '_score' => { 'order' => 'desc' } },
    { 'sort_by_views_per_year' => { 'order' => 'desc' } }
  ]
end

如果ElasticSearch random_score查询DSL开始支持类似于:max_doc_to_includemin_score属性,这将是非常有帮助的。这样我就可以像:

代码语言:javascript
运行
复制
{
  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
},
票数 0
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72622098

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档