升级spring-data-elasticsearch 4.2.1至4.3.0后相同文档评分不一致
问题根因
Spring Boot 2.6 绑定的 spring-data-elasticsearch 版本为 4.3.x,和 Spring Boot 2.5 对应的 4.2.x 版本相比存在一个未被重点标注的破坏性变更:查询默认的search_type从DFS_QUERY_THEN_FETCH调整为了QUERY_THEN_FETCH,两种查询模式的评分逻辑差异直接导致了你遇到的问题:
- 旧版本默认的
DFS_QUERY_THEN_FETCH模式:执行查询前会先向所有分片收集全局的词频、文档频率等评分依赖的统计信息,做分布式打分校准,因此即使内容完全相同的文档分布在不同分片,最终计算出的评分也是一致的。 - 新版本默认的
QUERY_THEN_FETCH模式:各分片仅基于本地存储的文档统计数据独立计算评分,不会提前做全局统计校准,和你之前的判断一致,多分片场景下,相同内容的文档会因为所在分片的本地词频、总文档数差异得到不同的评分结果,当你按最高评分拉取文档时,就会漏掉同内容但评分稍低的结果。
官方做这个调整的核心原因是DFS_QUERY_THEN_FETCH需要额外的一轮网络交互收集分片统计信息,性能开销更高,因此默认切换为性能更优的模式,但没有在升级文档中做足够醒目的提示,导致很多升级场景踩坑。
恢复旧版本行为的配置方案
你可以根据自己的业务场景选择以下任意一种配置方式,即可恢复到2.5版本的评分表现:
- 全局生效配置:如果项目中所有ES查询都需要一致的评分逻辑,可以在自定义ElasticsearchRestTemplate时修改默认SearchType,参考代码如下:
@Configuration public class EsConfig extends AbstractElasticsearchConfiguration { // 省略客户端、转换器等其他已有配置 @Override public ElasticsearchRestTemplate elasticsearchTemplate(ElasticsearchClient client, ElasticsearchConverter converter) { ElasticsearchRestTemplate template = new ElasticsearchRestTemplate(client, converter); // 改回旧版本默认的查询类型,保证跨分片评分一致 template.setDefaultSearchType(SearchType.DFS_QUERY_THEN_FETCH); return template; } }
- 单查询粒度配置:如果仅需要部分涉及精确评分的查询保持一致逻辑,不需要全局修改默认配置,可以在构建具体查询时单独指定查询类型:
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(/* 你的业务查询条件 */) // 单独为当前查询设置DFS查询模式 .withSearchType(SearchType.DFS_QUERY_THEN_FETCH) .build();
补充说明:如果你的索引设置为单分片,两种查询模式的评分结果不会有差异,但生产环境通常不会采用单分片配置,因此还是建议通过上述配置调整适配。
内容的提问来源于stack exchange,提问作者Moldavis
相关产品推荐
相关产品推荐

