Elasticsearch聚合分页,滚动聚合
基础用法
目前Elasticsearch支持聚合分页(滚动聚合)的目前只有复合聚合(Composite Aggregation)一种。滚动的方式类似于SearchAfter。
或者说页面上的“加载更多”;
复合聚合目前只支持3种聚合来源:
- 术语聚合(Terms)
- 直方图聚合(Histogram)
- 时间直方图聚合(Date Histogram)
为复合聚合添加聚合的参数为sources
DSL写法:
POST /indexname/_search
{
"aggs":{
"userAgg":{
"composite":{
"sources":[
{"user":{"terms":{"field":"username","order":"desc"}}}
],
"size":2
}
}
}
}
order
默认按自然顺序的升序排序(asc)
RestHighlevelClient写法:
//聚合
List<CompositeValuesSourceBuilder<?>> sources =
new ArrayList<>();
TermsValuesSourceBuilder fromAgg =
new TermsValuesSourceBuilder("user")
.field("username")
.order("desc");
sources.add(fromAgg);
CompositeAggregationBuilder multiAgg =
AggregationBuilders.composite(
"userAgg",
sources
).size(2);
响应示例:
{
"aggregations": {
"userAgg": {
"after_key": { #查询返回的最后一个复合桶。
"user": "zhangsan"
},
"buckets": [
{
"key": {
"user": "lisi"
},
"doc_count": 1
},
{
"key": {
"user": "zhangsan"
},
"doc_count": 2
}
]
}
}
}
RestHighlevelClient获取结果:
ParsedComposite userAgg =
searchResponse.getAggregations().get("userAgg");
List<ParsedComposite.ParsedBucket> buckets =
multiMailAgg.getBuckets();
for(ParseBucket bucket: buckets){
String username = bucket.getKey().get("user").toString();
}
在java中获取afterKey使用userAgg.afterKey()
翻页
如果要实现翻页,将响应值中的after_key
的值放入复合聚合的after
参数即可达到翻页的效果:
DSL:
POST /indexname/_search
{
"aggs":{
"userAgg":{
"composite":{
"sources":[
{"user":{"terms":{"field":"username"}}}
],
"size":2,
"after":{
"user": "zhangsan"
}
}
}
}
}
RestHighlevelClient写法:
//聚合
List<CompositeValuesSourceBuilder<?>> sources =
new ArrayList<>();
TermsValuesSourceBuilder fromAgg =
new TermsValuesSourceBuilder("user")
.field("username");
sources.add(fromAgg);
Map<String,Object> afterKey = new HashMap<>();
CompositeAggregationBuilder multiAgg =
AggregationBuilders.composite(
"userAgg",
sources
).size(2);
multiAgg.after(afterKey);
在java中需要获取每次响应中返回的afterKey,再将这个afterKey作为multiAgg.after()
的参数。
大概写法为:
//聚合
List<CompositeValuesSourceBuilder<?>> sources =
new ArrayList<>();
TermsValuesSourceBuilder fromAgg =
new TermsValuesSourceBuilder("user")
.field("username");
sources.add(fromAgg);
Map<String,Object> afterKey = null;
CompositeAggregationBuilder multiAgg =
AggregationBuilders.composite(
"userAgg",
sources
).size(2);
while(true){
if(afterKey!=null){
multiAgg.after(afterKey)
}
searchSourceBuilder.aggregation(multiAgg);
//执行查询获取响应
SearchResponse searchReseponse = ...
afterKey = ((ParsedComposite)searchReseponse.getAggregation().get("userAgg")).afterKey();
if(afterKey==null){
break;
}
}