有没有办法从弹性搜索索引中获取真正的随机样本?即一个从索引中检索任何文档的查询,概率为1/N
(其中N
是当前索引的文档数)?
作为后续问题:如果所有文档都有一些数字字段s
,是否有办法通过加权随机抽样获取文档,即获取文档i
的概率值s_i
等于s_i / sum(s_j for j in index)
?
答案 0 :(得分:32)
我知道这是一个老问题,但现在可以使用random_score, 使用以下搜索查询:
{
"size": 1,
"query": {
"function_score": {
"functions": [
{
"random_score": {
"seed": "1477072619038"
}
}
]
}
}
}
对我而言,它的速度非常快,约有200万份文件。
我使用当前时间戳作为种子,但您可以使用任何您喜欢的内容。最好的是如果你使用相同的种子,你将得到相同的结果。因此,您可以将用户的会话ID用作种子,所有用户将有不同的顺序。
答案 1 :(得分:5)
我知道从索引中获取随机文档(至少在版本< = 1.3.1中)的唯一方法是使用脚本:
sort: {
_script: {
script: "Math.random() * 200000",
type: "number",
params: {},
order: "asc"
}
}
您可以使用该脚本根据记录的某些字段进行一些加权。
将来他们可能会添加更复杂的内容,但您可能不得不向ES小组请求。
答案 2 :(得分:5)
您可以将random_score与function_score
查询一起使用。
{
"size":1,
"query": {
"function_score": {
"functions": [
{
"random_score": {
"seed": 11
}
}
],
"score_mode": "sum",
}
}
}
不好的一点是,这将对每个文档应用随机分数,对文档进行排序,然后返回第一个文档。我不知道任何足够聪明的东西只能随机选择一份文件。
答案 3 :(得分:2)
您可以使用random_score
随机排序回复或检索大概1/N
概率的文档。
附加说明:
https://github.com/elastic/elasticsearch/issues/1170 https://github.com/elastic/elasticsearch/issues/7783
答案 4 :(得分:0)
嵌套方式:
var result = _elastic.Search<dynamic>(s => s
.Query(q => q
.FunctionScore(fs => fs.Functions(f => f.RandomScore())
.Query(fq => fq.MatchAll()))));
原始查询方式:
GET index-name/_search
"size": 1,
"query": {
"function_score": {
"query" : { "match_all": {} },
"random_score": {}
}
}
}