Elasticsearch Java API 7.17.x实现带top_hits子聚合的date_range聚合
Elasticsearch Java API Client 7.17.x 日期范围嵌套聚合实现
目标需求
在Spring Boot项目中使用Elasticsearch Java API Client 7.17.x版本,实现日期范围聚合+嵌套top_hits子聚合,修正原始DSL括号结构错误后,目标查询逻辑如下:
{ "size": 0, "aggs": { "range": { "date_range": { "field": "timestamp", "ranges": [ { "to": "now-2d" } ] }, "aggs": { "hits": { "top_hits": { "_source": { "includes": ["Id", "timestamp"] } } } } } } }
初始实现的问题
初始编写的代码存在两处核心错误,导致无法返回正确结果:
top_hits子聚合被平级挂载在搜索请求的根聚合下,没有作为日期范围聚合的嵌套子聚合存在,生成的DSL结构和预期不符- 日期范围的
to参数直接传入expr字符串,不符合API的类型校验要求
初始错误代码示例:
SearchResponse<MyDto> response = client.search(b -> b .index("test-index") .size(0) .aggregations("range",a->a.dateRange(DateRangeAggregation.of(d->d .field("timestamp").ranges(r->r.to(t->t.expr("now-2d")))))) .aggregations("hits", a -> a .topHits(h->h.source(SourceConfig.of(c->c.filter(f->f.includes(Arrays.asList("Id", "timestamp"))))))), MyDto.class );
正确实现代码
调试阶段写出的获取doc_count的写法完全符合API规范,在此基础上补全嵌套子聚合定义即可实现完整需求,完整可运行代码如下:
import co.elastic.clients.elasticsearch._types.FieldDateMath; import co.elastic.clients.elasticsearch.core.SearchResponse; import co.elastic.clients.elasticsearch.core.search.Hit; import co.elastic.clients.elasticsearch._types.aggregations.DateRangeBucket; import java.util.Arrays; import java.util.List; // 构建搜索请求 SearchResponse<MyDto> response = client.search(b -> b .index("test-index") .size(0) .aggregations("range", agg -> agg // 定义外层日期范围聚合 .dateRange(range -> range .field("timestamp") .ranges(r -> r .to(FieldDateMath.of(v -> v.expr("now-2d"))) ) ) // 定义嵌套在日期范围聚合下的top_hits子聚合 .aggregations("hits", subAgg -> subAgg .topHits(hits -> hits .source(source -> source .filter(filter -> filter .includes(Arrays.asList("Id", "timestamp")) ) ) ) ) ), MyDto.class ); // 读取聚合结果 List<DateRangeBucket> buckets = response.aggregations() .get("range") .dateRange() .buckets() .array(); for (DateRangeBucket bucket : buckets) { // 读取当前bucket的文档数 long docCount = bucket.docCount(); // 读取子聚合top_hits的命中结果 List<Hit<MyDto>> hitDetails = bucket.aggregations() .get("hits") .topHits() .hits() .hits(); // 按需处理命中的文档数据 }
关键注意事项
- 嵌套子聚合必须定义在父聚合的构建逻辑内,通过父聚合builder的
aggregations()方法添加,不能和父聚合平级挂载在搜索请求根节点 - 动态日期表达式(如
now-2d这类相对时间值)必须通过FieldDateMath.of()封装后传入范围参数,直接传入字符串会触发类型校验错误 - 聚合结果读取时要和定义的聚合类型严格对应:日期范围聚合结果调用
.dateRange()方法获取,top_hits子聚合结果调用.topHits()方法获取,类型不匹配会触发解析异常
内容的提问来源于stack exchange,提问作者Pompompurin
相关产品推荐
相关产品推荐

