ElasticSearch 聚合之Java客户端实现聚合

一、聚合请求构建

1. 核心工具类

  • SearchRequest:构建搜索请求对象
  • AggregationBuilders:提供各类聚合的静态方法

2. 聚合三要素

要素描述代码示例
聚合名称自定义标识符"brand_agg"
聚合类型如terms/stats等AggregationBuilders.terms()
聚合字段需为keyword/数值/日期类型"brand.keyword"

3. 基础桶聚合示例

// 创建请求对象
SearchRequest request = new SearchRequest("items");
request.source()
    .size(0)  // 不返回文档数据
    .aggregation(
        AggregationBuilders.terms("brand_agg")  // 聚合名称+类型
            .field("brand")            // 聚合字段
            .size(20)                         // 返回前20个品牌
    );

二、聚合结果解析

1. 解析流程

// 发送请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);

// 1. 获取聚合根节点
Aggregations aggregations = response.getAggregations();

// 2. 根据名称获取指定聚合结果
Terms brandTerms = aggregations.get("brand_agg");

// 3. 提取桶列表
List<? extends Terms.Bucket> buckets = brandTerms.getBuckets();

// 4. 遍历处理每个桶
for (Terms.Bucket bucket : buckets) {
    String brand = bucket.getKeyAsString();      // 品牌名称
    long docCount = bucket.getDocCount();        // 文档数量
    System.out.println(brand + ": " + docCount);
}

2. 关键API说明

  • response.getAggregations():获取所有聚合结果
  • aggregations.get("聚合名称"):按名称获取具体聚合
  • Terms.Bucket:代表单个分组结果,包含:
    • getKeyAsString():分组字段值
    • getDocCount():组内文档数量

三、嵌套聚合示例(桶聚合+度量聚合)

1. 统计各品牌价格指标

SearchRequest request = new SearchRequest("items");
request.source()
    .size(0)
    .aggregation(
        AggregationBuilders.terms("brand_agg")
            .field("brand")
            .subAggregation(  // 嵌套子聚合
                AggregationBuilders.stats("price_stats")
                    .field("price")
            )
    );

2. 解析嵌套结果

Terms brandTerms = aggregations.get("brand_agg");
for (Terms.Bucket bucket : brandTerms.getBuckets()) {
    String brand = bucket.getKeyAsString();
    
    // 获取子聚合结果
    Stats priceStats = bucket.getAggregations().get("price_stats");
    
    System.out.println("品牌: " + brand);
    System.out.println("平均价格: " + priceStats.getAvg());
    System.out.println("最高价格: " + priceStats.getMax());
}

四、完整代码模板

@Test
void testAggregation() throws IOException {
    // 1. 创建请求
    SearchRequest request = new SearchRequest("index_name");
    
    // 2. 构建聚合条件
    request.source()
        .size(0)
        .aggregation(
            AggregationBuilders.terms("聚合名称")
                .field("字段名.keyword")
                .size(返回数量)
                .subAggregation(  // 可选嵌套
                    AggregationBuilders.avg("avg_price")
                        .field("price")
                )
        );
    
    // 3. 发送请求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    
    // 4. 解析结果
    Aggregations aggs = response.getAggregations();
    Terms terms = aggs.get("聚合名称");
    
    terms.getBuckets().forEach(bucket -> {
        String key = bucket.getKeyAsString();
        long count = bucket.getDocCount();
        // 处理嵌套聚合...
    });
}

五、常见问题排查

1. 获取不到聚合结果

  • 检查字段是否为keyword类型(需.keyword后缀)
  • 确认聚合名称拼写一致
  • 验证聚合字段是否存在映射

2. 类型转换异常

// 错误:直接强制转换
Stats stats = (Stats) aggregation;

// 正确:通过名称获取
Stats stats = aggregations.get("price_stats");

3. 性能优化

  • 对高频聚合字段设置fielddata: true
  • 限制返回桶数量(.size(100)
  • 避免在大文本字段上聚合

六、最佳实践建议

  1. 封装工具方法:将聚合解析逻辑封装成可复用方法
  2. 异常处理:添加空指针检查
if (aggregations != null) {
    Terms terms = aggregations.get("brand_agg");
    if (terms != null) {
        // 处理逻辑...
    }
}
  1. 结果格式化:将聚合结果转为DTO对象方便前端展示
List<BrandStatDTO> results = terms.getBuckets().stream()
    .map(bucket -> new BrandStatDTO(
        bucket.getKeyAsString(),
        bucket.getDocCount()
    ))
    .collect(Collectors.toList());
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值