【发布时间】:2019-07-15 16:30:54
【问题描述】:
我已经运行 Rails 网站几年了,一些文章是根据权重字段从数据库中提取的。数据结构为:
{name: 'Content Piece 1', weight: 50}
{name: 'Content Piece 2', weight: 25}
{name: 'Content Piece 3', weight: 25}
我最初编写的 Ruby 代码如下所示:
choices = []
sum = articles.inject(0.0) { |sum, article|
sum += listing['weight']
}
pick = rand(sum)
choices << articles.detect { |listing|
if pick <= listing['weight']
true
else
pick -= listing['weight']
false
end
}
这很适合提取每个内容并尊重重量。在整个数据集上运行此代码 100 次后,我多次根据权重得到分布相当好的内容片段:
100.times do
choices = []
sum = articles.inject(0.0) { |sum, article|
sum += listing['weight']
}
pick = rand(sum)
choices << articles.detect { |listing|
if pick <= listing['weight']
true
else
pick -= listing['weight']
false
end
}
end
{:total_runs=>100, "Content Piece 1"=>51, "Content Piece 2"=>22, "Content Piece 3"=>27}
{:total_runs=>100, "Content Piece 1"=>53, "Content Piece 2"=>30, "Content Piece 3"=>17}
我现在开始更频繁地使用 ElasticSearch,我希望我可以在 ES 中索引数据并根据权重提取内容。
我发现了一篇 SO 帖子,其中讨论了非常相似的内容,可以在这里找到:
Weighted random sampling in Elasticsearch
我已拉出搜索查询并对其进行了更改以匹配我的数据结构:
{
"sort": ["_score"],
"size": 1,
"query": {
"function_score": {
"functions": [
{
"random_score": {}
},
{
"field_value_factor": {
"field": "weight",
"modifier": "none",
"missing": 0
}
}
],
"score_mode": "multiply",
"boost_mode": "replace"
}
}
}
这个查询确实尊重权重,并且拉出权重为 50 的内容片段比其他 2 个权重为 25 的内容片段多很多,但它不会将内容分配到总权重 100 中,如果这是有道理的。我运行此查询 100 次并得到如下结果:
{:total_runs=>100, "Content Piece 1"=>70, "Content Piece 2"=>22, "Content Piece 3"=>8}
{:total_runs=>100, "Content Piece 1"=>81, "Content Piece 2"=>7, "Content Piece 3"=>12}
{:total_runs=>100, "Content Piece 1"=>90, "Content Piece 2"=>3, "Content Piece 3"=>7}
由于我是 ES 新手,并且仍在学习查询、评分等的细节,我想知道是否有人可以提供解决方案来更模仿我编写的 Ruby 代码,以便更有效地根据权重分配内容满分 100 分。Painless 脚本是否适用于移植 Ruby 代码?
我希望这是有道理的,如果您还有任何问题可以帮助解释我想要实现的目标,请告诉我。谢谢!
【问题讨论】:
标签: elasticsearch random weighted