【问题标题】:With spring-data-elasticsearch and searching for similar documents, how to get similarity score?使用 spring-data-elasticsearch 并搜索相似文档,如何获得相似度分数?
【发布时间】:2021-12-20 11:04:26
【问题描述】:

我正在使用最新版本的 elasticsearch(在 docker 中)和一个 spring boot(最新版本)应用程序,我尝试在其中搜索类似的文档。我的文档类有一个字符串字段:

@Field(
        name = "description",
        type = FieldType.Text,
        fielddata = true,
        analyzer = "icu_analyzer",
        termVector = TermVector.with_positions_offsets,
        similarity = Similarity.BM25)
private String description;

当我使用内置的searchSimilar 方法时,我的查询得到了很多结果:

public Page<BookInfo> findSimilarDocuments(final long id) {
    return bookInfoRepository.findById(id)
            .map(bookInfo -> bookInfoRepository.searchSimilar(bookInfo, new String[]{"description"}, pageable))
            .orElse(Page.empty());
}

但是,我不知道这些文档有多相似,因为它只是我的 Document 对象的一个​​页面。如果能够看到相似度得分,或者在执行查询时设置相似度阈值,那就太好了。我应该做些什么不同的事情吗?

【问题讨论】:

    标签: elasticsearch spring-data-elasticsearch


    【解决方案1】:

    我刚看了一下,现有方法Page&lt;T&gt; searchSimilar(T entity, @Nullable String[] fields, Pageable pageable)早在2013年就被添加到ElasticsearchRepository接口中,它只是返回一个Page&lt;T&gt;,其中不包含任何分数信息。 从 Spring Data Elasticsearch 4.0 版开始,分数信息可用,当您查看实现时,您会发现它已从函数的返回值中剥离,以便遵守接口中的方法签名:

    public Page<T> searchSimilar(T entity, @Nullable String[] fields, Pageable pageable) {
    
        Assert.notNull(entity, "Cannot search similar records for 'null'.");
        Assert.notNull(pageable, "'pageable' cannot be 'null'");
    
        MoreLikeThisQuery query = new MoreLikeThisQuery();
        query.setId(stringIdRepresentation(extractIdFromBean(entity)));
        query.setPageable(pageable);
    
        if (fields != null) {
            query.addFields(fields);
        }
    
        SearchHits<T> searchHits = execute(operations -> operations.search(query, entityClass, getIndexCoordinates()));
        SearchPage<T> searchPage = SearchHitSupport.searchPageFor(searchHits, pageable);
        return (Page<T>) SearchHitSupport.unwrapSearchHits(searchPage);
    }
    

    您可以实现一个自定义存储库片段(请参阅https://docs.spring.io/spring-data/elasticsearch/docs/4.2.6/reference/html/#repositories.custom-implementations),该片段提供它自己的方法实现,该方法返回一个SearchPage&lt;T&gt;

    public SearchPage<T> searchSimilar(T entity, @Nullable String[] fields, Pageable pageable) {
    
        Assert.notNull(entity, "Cannot search similar records for 'null'.");
        Assert.notNull(pageable, "'pageable' cannot be 'null'");
    
        MoreLikeThisQuery query = new MoreLikeThisQuery();
        query.setId(stringIdRepresentation(extractIdFromBean(entity)));
        query.setPageable(pageable);
    
        if (fields != null) {
            query.addFields(fields);
        }
    
        SearchHits<T> searchHits = execute(operations -> operations.search(query, entityClass, getIndexCoordinates()));
        SearchPage<T> searchPage = SearchHitSupport.searchPageFor(searchHits, pageable);
        return searchPage;
    }
    

    SearchPage&lt;T&gt; 是一个包含SearchHit&lt;T&gt; 实例的页面;这些包含实体和分数等附加信息。

    【讨论】:

    • 谢谢你。它非常接近,尽管搜索结果中的分数返回为“NaN”。我必须使用本机查询才能使其正常工作。
    • 奇怪。我正在使用调试器查看此方法的测试代码中返回的结果,并且分数有值。
    猜你喜欢
    • 2020-07-30
    • 2021-01-03
    • 2011-02-21
    • 2015-12-30
    • 1970-01-01
    • 2017-02-27
    • 2014-02-25
    • 2013-02-06
    • 2017-04-18
    相关资源
    最近更新 更多