You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 18:53:15