赞
踩
es聚合的应用场景是很多,不过,有时候,还会有多个字段聚合,聚合后分页,聚合后having的需求
//构造查询对象 SearchRequest baseSubOrderIndexRequest = CloudBaseQueryBuilder.getBaseSubOrderIndexRequest(); SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); BoolQueryBuilder boolQuery = CloudBaseQueryBuilder.getBaseSubOrderDimensionBoolQuery(vo); // 采购方式 if(vo.getBugTypes()!=null && vo.getBugTypes().size()>0){ boolQuery.filter(QueryBuilders.termsQuery("buyType",vo.getBugTypes())); } if(StringUtils.isNotEmpty(vo.getSupplierName())){ boolQuery.filter(QueryBuilders.termQuery("supplierName",vo.getSupplierName())); } if(StringUtils.isNotEmpty(vo.getUnitName())){ boolQuery.filter(QueryBuilders.termQuery("unitName",vo.getUnitName())); } sourceBuilder.query(boolQuery); //最外层的聚合 TermsAggregationBuilder percentageInfo = AggregationBuilders.terms("percentage_info").field(vo.getType().equals("1")?"unitName.keyword":"supplierName.keyword").size(Integer.MAX_VALUE).order(BucketOrder.aggregation(getTurnOverSumName(),false)); //在第一层聚合的基础上 percentageInfo.subAggregation( AggregationBuilders.terms("provinceName") .field("provinceName.keyword") .size(1)); percentageInfo.subAggregation( AggregationBuilders.terms("cityName") .field("cityName.keyword") .size(1)); percentageInfo.subAggregation( AggregationBuilders.terms("areaName") .field("areaName.keyword") .size(1)); percentageInfo.subAggregation( AggregationBuilders.terms("cgUnitIndustry") .field("cgUnitIndustry.keyword") .size(1));
Elasticsearch 聚合后是不支持分页的
性能角度——聚合分页会在大量的记录中产生性能问题。
正确性角度——聚合的文档计数不准确.
但是,公司的一些要求,要进行分页,大致有两种思路
// 聚合分页
if ((!ObjectUtils.isEmpty(vo.getPageNo())) && (!ObjectUtils.isEmpty(vo.getPageSize()))) {
percentageInfo.subAggregation(new BucketSortPipelineAggregationBuilder("bucket_field", Arrays.asList(new FieldSortBuilder(getTurnOverSumName()).order(SortOrder.DESC))).from((vo.getPageNo() - 1) * vo.getPageSize()).size(vo.getPageSize()));
}
//分组总条数
List<? extends Terms.Bucket> totalBuckets = ((Terms) masterAggregations.get("percentage_info_total")).getBuckets();
//分组总条数
totalBuckets.size();
percentageInfo.subAggregation(AggregationBuilders
.sum("turnOverSum")
.field("totalPrice"));
聚合之后还不能满足我们的需求,比如要过滤出价格大于某个值的数据
Elasticsearch 提供了bucketSelector的写法
if(StringUtils.isNotEmpty(vo.getTotalPrice())){
//(1) 设置脚本
Script script = new Script("params.turnOverSum >="+vo.getTotalPrice());
//(2) 声明BucketPath,用于后面的bucket筛选
Map<String, String> bucketsPathsMap = new HashMap<>(2);
bucketsPathsMap.put("turnOverSum", "turnOverSum");
//(3) 构建bucket selector 实现having条件筛选过滤
BucketSelectorPipelineAggregationBuilder bs =
PipelineAggregatorBuilders.bucketSelector("having", bucketsPathsMap,script);
percentageInfo.subAggregation(bs);
}
sourceBuilder.aggregation(percentageInfo);
baseSubOrderIndexRequest.source(sourceBuilder);
SearchResponse response = elasticsearchClient.search(baseSubOrderIndexRequest, RequestOptions.DEFAULT);
log.debug(()->sourceBuilder.toString());
List<DataReportDTO> list=new ArrayList<>();
Aggregations masterAggregations = response.getAggregations();
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。