使用spring-data-elasticsearch检索相似文档时如何获取相似度分数
实现方案可分为以下3步调整:
1. 自定义结果封装类
内置searchSimilar仅返回实体数据,首先定义DTO同时存储文档内容和相似度分数:
public class SimilarBookDoc { // 原文档实体 private BookInfo bookInfo; // ES返回的相似度打分 private Float similarityScore; public SimilarBookDoc(BookInfo bookInfo, Float similarityScore) { this.bookInfo = bookInfo; this.similarityScore = similarityScore; } // 按需添加getter、setter }
2. 替换内置searchSimilar为自定义MLT查询
内置方法没有开放分数获取、阈值过滤的能力,直接通过ElasticsearchOperations构建原生More Like This查询即可:
@Autowired private BookInfoRepository bookInfoRepository; @Autowired private ElasticsearchOperations elasticsearchOperations; public Page<SimilarBookDoc> findSimilarDocuments(long id, float minScoreThreshold, Pageable pageable) { Optional<BookInfo> sourceDocOpt = bookInfoRepository.findById(id); if (sourceDocOpt.isEmpty()) { return Page.empty(pageable); } BookInfo sourceDoc = sourceDocOpt.get(); // 获取实体对应的索引名 IndexCoordinates index = elasticsearchOperations.getIndexCoordinatesFor(BookInfo.class); // 构建原生MLT查询,逻辑和原searchSimilar完全对齐 Query query = NativeQuery.builder() .withQuery(q -> q .moreLikeThis(mlt -> mlt // 指定匹配字段,对应原方法的字段数组 .fields("description") // 指定以查询到的源文档作为相似基准 .like(like -> like.document(index.getIndexName(), String.valueOf(id))) // 可按需调整MLT的召回规则参数 .minTermFreq(1) .minDocFreq(1) ) ) .withPageable(pageable) // 设置相似度阈值,低于阈值的结果直接过滤不返回 .withMinScore(minScoreThreshold) .build(); // 执行查询同时获取实体和打分 SearchHits<BookInfo> searchHits = elasticsearchOperations.search(query, BookInfo.class); // 转换为自定义结果格式 List<SimilarBookDoc> resultList = searchHits.get() .map(hit -> new SimilarBookDoc(hit.getContent(), hit.getScore())) .toList(); // 封装为分页对象返回 return new PageImpl<>(resultList, pageable, searchHits.getTotalHits()); }
3. 按需调整查询参数
如果对召回效果不满意,可调整MLT查询的minShouldMatch、maxQueryTerms、stopWords等参数,适配业务场景。
注意:你已配置的
termVector = TermVector.with_positions_offsets已经可以大幅提升MLT查询的性能,不需要额外修改字段映射配置。
内容的提问来源于stack exchange,提问作者Steve Storck
相关产品推荐
相关产品推荐

