Elasticsearch中filtered query下random_score返回0,但match_all正常的问题
问题:function_score搭配bool过滤时random_score分数为0.0
使用包含random_score函数的function_score查询,搭配match_all时能正常分配随机分数;但在基于字段存在性过滤的bool query中使用相同random_score,所有文档分数均为0.0。使用版本为OpenSearch 7.10.2。
正常的match_all脚本
curl -X POST "https://[my_elasticsearch_server]/_scripts/search_unclaimed_records" -H 'Content-Type: application/json' -d ' { "script": { "lang": "mustache", "source": { "size": 1, "seq_no_primary_term": true, "query": { "function_score": { "functions": [ { "random_score": {} } ], "query": { "match_all": {} } } } } } }'
异常的字段过滤脚本
curl -X POST "https://[my_elasticsearch_server]/_scripts/search_unclaimed_records" -H 'Content-Type: application/json' -d ' { "script": { "lang": "mustache", "source": { "size": 1, "seq_no_primary_term": true, "query": { "function_score": { "query": { "bool": { "should": [ { "bool": { "must_not": { "exists": { "field": "locked_until" } } } } ], "minimum_should_match": 1 } }, "functions": [ { "random_score": {} } ] } } } } }'
注:第一个脚本正常分配非零分数,第二个脚本虽能正确过滤文档,但所有结果分数均为0.0。
尝试的修正脚本
基于建议尝试了以下写法,询问是否符合预期:
curl -X POST "https://[my_elasticsearch_server]/_scripts/search_unclaimed_records" -H 'Content-Type: application/json' -d ' { "script": { "lang": "mustache", "source": { "size": 1, "seq_no_primary_term": true, "query": { "bool": { "filter": [ { "bool": { "must_not": { "exists": { "field": "locked_until" } } } } ], "should": [ { "function_score": { "functions": [ { "random_score": {} } ] } } ] } } } } }'
问题原因
异常脚本中,function_score内部的bool查询使用should+minimum_should_match:1结构,这类查询的原始匹配分数为0(must_not exists属于无评分的过滤类逻辑)。而function_score默认的分数计算逻辑是原始查询分数 × 函数分数,0乘以任何随机分数结果仍然是0。
第一个脚本中match_all的原始分数为1.0,因此1×随机分数能得到正常的非零结果。
修正脚本的有效性
你尝试的写法是完全正确的,原因如下:
- 将字段存在性过滤放到
bool.filter中,既完成了文档筛选,又不会参与评分计算(filter内的查询仅做过滤,不影响分数)。 - 在
should中放入不带内部query的function_score(默认匹配所有文档),random_score生成的随机分数会直接作为should子句的分数返回,最终每个匹配文档的分数就是随机生成的非零值。
其他等价写法
除了你尝试的方式,还有两种写法可以达到同样效果:
- 给
function_score添加boost_mode: replace,直接用函数分数替换原始查询分数:
curl -X POST "https://[my_elasticsearch_server]/_scripts/search_unclaimed_records" -H 'Content-Type: application/json' -d ' { "script": { "lang": "mustache", "source": { "size": 1, "seq_no_primary_term": true, "query": { "function_score": { "query": { "bool": { "must_not": { "exists": { "field": "locked_until" } } } }, "functions": [ { "random_score": {} } ], "boost_mode": "replace" } } } } }'
- 简化
bool查询,直接使用must_not exists(无需嵌套should),搭配boost_mode: replace:
curl -X POST "https://[my_elasticsearch_server]/_scripts/search_unclaimed_records" -H 'Content-Type: application/json' -d ' { "script": { "lang": "mustache", "source": { "size": 1, "seq_no_primary_term": true, "query": { "function_score": { "query": { "bool": { "must_not": { "exists": { "field": "locked_until" } } } }, "functions": [ { "random_score": {} } ], "boost_mode": "replace" } } } } }'
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

