在 spring-data-elasticsearch 中使用 ElasticsearchTemplate 获取 ID 的计数和列表

Getting count and list of ids using ElasticsearchTemplate in spring-data-elasticsearch

我正在为一个项目使用 spring-data-elasticsearch 来为其提供全文搜索功能。我们将真实数据保存在关系数据库中,并将相关元数据与相应的 id 一起保存在 elasticsearch 中。所以对于搜索结果,只有id字段是必需的,因为实际数据将从关系数据库中检索。

我正在根据搜索条件构建搜索查询,然后执行 queryForIds():

    SearchQuery searchQuery = new NativeSearchQueryBuilder()
            .withIndices(indexName)
            .withTypes(typeName)
            .withQuery(getQueryBuilder(searchParams))
            .withPageable(pageable)
            .build();

    return elasticsearchTemplate.queryForIds(searchQuery);

如果我还需要该特定 searchQuery 的总计数,我可以进行另一个 elasticsearchTemplate.count(searchQuery) 调用,但据我所知,这将是多余的。我认为有一种方法可以通过在一次调用中使用 elasticsearchTemplate.queryForPage() 之类的东西来获取 id 列表和总计数。

此外,我可以在 queryForPage(SearchQuery query, Class<T> clazz, SearchResultMapper mapper) 中使用未使用 @Document 注释的自定义 class 吗?实际文档 class 确实很大,如果我不确定传递大 class 是否会对引擎造成任何额外负载,因为有超过 100 个字段需要 json 映射,但我只需要 id 字段。无论如何,我都会在查询构建器中有一个 .withFields("id")

如果你想阻止对 elasticsearch 的两次调用,我建议编写一个自定义的 ResultsExtractor:

SearchQuery searchQuery = new NativeSearchQueryBuilder().withIndices(indexName)
        .withTypes(typeName)
        .withQuery(queryBuilder)
        .withPageable(pageable)
        .build();
SearchResult result = template.query(searchQuery, new ResultsExtractor<SearchResult>() {

    @Override
    public SearchResult extract(SearchResponse response) {
        long totalHits = response.getHits()
                .totalHits();
        List<String> ids = new ArrayList<String>();
        for (SearchHit hit : response.getHits()) {
            if (hit != null) {
                ids.add(hit.getId());
            }
        }
        return new SearchResult(ids, totalHits);
    }
});
System.out.println(result.getIds());
System.out.println(result.getCount());

其中 SearchResult 是自定义 class:

public class SearchResult {

    List<String> ids;
    long count;

    //getter and setter
}

这样你就可以从elasticsearch中得到你需要的信息SearchResponse

关于你的第二个问题:据我所知,当调用 queryForPage(SearchQuery query, Class<T> clazz, SearchResultMapper mapper) 传递的 class 未针对 @Document 注释进行检查。试试吧!

也可以考虑使用 AggregatedPage<T>。可以像Pageable<T>.

一样获取总记录数、总页数、当前页记录数等
SearchQuery searchQuery = new NativeSearchQueryBuilder().withIndices(indexName)
        .withTypes(typeName)
        .withQuery(queryBuilder)
        .withPageable(pageable)
        .build();

AggregatedPage<ElasticDTO> queryResult = elasticsearchTemplate.queryForPage(searchQuery , ElasticDTO.class);