在 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);
我正在为一个项目使用 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);