Spring Data Elasticsearch 4.4.x:如何从SearchHits中获取聚合结果?
解决方案(Spring Data Elasticsearch 4.4.11 / Spring Boot 2.7.11)
1. 先纠正聚合字段错误
你当前构建聚合时使用的field("projects.projectId")有误,实体类中Bug的关联字段是单数project,应改为field("project.projectId")。
2. 定义结果封装类
创建DistinctProject类,用来存储每个项目的ID、名称和对应的Bug数量:
@Data @AllArgsConstructor public class DistinctProject { private String projectId; private String projectName; private long bugCount; }
3. 完整的聚合结果解析代码
修改getDistinctProjects方法,通过AggregationsContainer正确解析聚合结果:
@Autowired private ElasticsearchOperations elasticsearchOperations; public List<DistinctProject> getDistinctProjects() { // 构建terms聚合:按projectId分组,嵌套top_hits获取项目名称 TermsAggregationBuilder aggregation = AggregationBuilders .terms("distinct_projects") .field("project.projectId") .size(10) .subAggregation(AggregationBuilders .topHits("project_details") .size(1) .fetchSource(new String[]{"project.name", "project.projectId"}, null)); // 构建查询,设置size=0以忽略原始Bug文档,只返回聚合结果 NativeSearchQuery searchQuery = new NativeSearchQueryBuilder() .withAggregations(aggregation) .withSize(0) .build(); SearchHits<Bug> searchHits = elasticsearchOperations.search(searchQuery, Bug.class); // 从SearchHits中提取聚合容器并转换为ElasticsearchAggregations AggregationsContainer<?> aggregationsContainer = searchHits.getAggregations(); if (aggregationsContainer instanceof ElasticsearchAggregations) { ElasticsearchAggregations aggregations = (ElasticsearchAggregations) aggregationsContainer; // 获取顶级terms聚合 Terms termsAggregation = aggregations.get("distinct_projects"); List<DistinctProject> result = new ArrayList<>(); // 遍历每个分组Bucket for (Terms.Bucket bucket : termsAggregation.getBuckets()) { String projectId = bucket.getKeyAsString(); long bugCount = bucket.getDocCount(); // 解析子聚合top_hits,提取项目名称 TopHits topHits = bucket.getAggregations().get("project_details"); SearchHits<Bug> projectHits = elasticsearchOperations.searchHits(topHits, Bug.class); String projectName = ""; if (!projectHits.isEmpty()) { Project project = projectHits.getSearchHit(0).getContent().getProject(); if (project != null) { projectName = project.getName(); } } result.add(new DistinctProject(projectId, projectName, bugCount)); } return result; } return Collections.emptyList(); }
关键解析点
withSize(0):必须添加,避免Elasticsearch返回默认的10条Bug文档,节省资源开销。AggregationsContainer转换:Spring Data Elasticsearch 4.x中SearchHits.getAggregations()返回AggregationsContainer<?>,需强转为ElasticsearchAggregations才能操作底层Elasticsearch聚合对象。- 子聚合解析:通过
bucket.getAggregations().get("project_details")获取top_hits子聚合,再转换为SearchHits<Bug>提取项目名称。
备选简化方案:直接解析JSON
如果嵌套聚合解析逻辑复杂,可直接将聚合结果转为JSON后解析:
// 获取聚合结果的JSON字符串 String aggregationsJson = aggregations.toJson(); // 使用Jackson解析JSON ObjectMapper mapper = new ObjectMapper(); JsonNode rootNode = mapper.readTree(aggregationsJson); // 按需遍历JSON节点提取字段...
内容的提问来源于stack exchange,提问作者Sriram Sridharan
相关产品推荐
相关产品推荐

