ES聚合嵌套参数拼接

14 篇文章 1 订阅

ES java 请求ES聚合嵌套参数拼接

目录

请求的参数:

代码:

1,StrTermNextScript:

2,模拟数据

3,测试:

总结:


 ​    使用Java请求es聚合查询,这时候使用RestHighLevelClient 进行请求查询,无论是拼接参数,还是处理值都是麻烦些的。如果使用Commons-httpclient里面的 HttpClient进行请求,这时候拼接参数查询就直接是es的语法了,处理值也方便些,没有那么多的类型。

使用 RestHighLevelClient 处理的时候,该如何处理参数呢?

查询query的时候,可以使用

QueryBuilder queryBuilder = QueryBuilders.wrapperQuery(sourceExpr);
 searchSourceBuilder.query(queryBuilder);

处理aggs参数的时候,就没了,得手动一个个拼接。

过程:

请求的参数:

 

{
	"size": 0,
	"aggs": {
		"colors": {
			"terms": {
				"field": "color.keyword"
			},
			"aggs": {
				"gap_price": {
					"bucket_script": {
						"buckets_path": {
							"deal0": "max_price",
							"deal1": "min_price"
						},
						"script": "params.deal0 - params.deal1"
					}
				},
				"max_price": {
					"sum": {
						"field": "price"
					}
				},
				"min_price": {
					"value_count": {
						"field": "material.keyword"
					}
				}
			}
		}
	}
}

代码:

引用部分参考《es 聚合查询 语法和例子》

1,StrTermNextScript:

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.elasticsearch.script.Script;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.elasticsearch.search.aggregations.bucket.range.DateRangeAggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.range.RangeAggregationBuilder;
import org.elasticsearch.search.aggregations.pipeline.PipelineAggregatorBuilders;
import org.elasticsearch.search.aggregations.pipeline.bucketscript.BucketScriptPipelineAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.joda.time.DateTimeZone;

import java.util.List;
import java.util.Map;

public class StrTermNextScript {

    /**
     *  字符型的拼接
     *   第一层用 searchSourceBuilder 加
     */
    private static void joinEsStrAggs(Map<String,Object> aggsMap, SearchSourceBuilder searchSourceBuilder) {
        Map<String,Object> aggsNameMap = (Map<String, Object>) aggsMap.get("aggs");
        AggregationBuilder aggregationBuilder;

        for (Map.Entry name : aggsNameMap.entrySet()) {
            String aggName = name.getKey().toString();

            Map<String,Object> valueMap = (Map<String, Object>) name.getValue();
            for (Map.Entry value : valueMap.entrySet()) {
                String aggType = value.getKey().toString();
                Map<String,Object> fieldMap = (Map<String, Object>) value.getValue();
                aggregationBuilder = setAggsBuilders(aggName,aggType,fieldMap);
                if("terms".equals(aggType)){
                    Map<String,Object> innerAggsMap = (Map<String, Object>) valueMap.get("aggs");
                    if(MapUtils.isNotEmpty(innerAggsMap)){
                        joinSecEsStrAggs(innerAggsMap, aggregationBuilder);
                    }
                }
                if(aggregationBuilder != null){
                    searchSourceBuilder.aggregation(aggregationBuilder);
                }
            }
        }

    }


    /**
     *  字符型的拼接
     * 第二层用 aggregationBuilder 的 subAggregation 方法添加后面的内容
     */
    private static void joinSecEsStrAggs(Map<String,Object> aggsNameMap, AggregationBuilder allAggregationBuilder) {

        AggregationBuilder aggregationBuilder;
        for (Map.Entry name : aggsNameMap.entrySet()) {
            String aggName = name.getKey().toString();

            Map<String,Object> valueMap = (Map<String, Object>) name.getValue();
            for (Map.Entry value : valueMap.entrySet()) {
                String aggType = value.getKey().toString();
                Map<String,Object> fieldMap = (Map<String, Object>) value.getValue();
                aggregationBuilder = setAggsBuilders(aggName,aggType,fieldMap);
                if("terms".equals(aggType)){
                    Map<String,Object> innerAggsMap = (Map<String, Object>) valueMap.get("aggs");
                    if(MapUtils.isNotEmpty(innerAggsMap)){
                        joinSecEsStrAggs(innerAggsMap, aggregationBuilder);
                    }
                }
                if("bucket_script".equals(aggType)){
                    BucketScriptPipelineAggregationBuilder bucketScript = getBucketScript(aggName,fieldMap);
                    if(aggregationBuilder != null){
                        aggregationBuilder.subAggregation(bucketScript);
                    }else{
                        allAggregationBuilder.subAggregation(bucketScript);
                    }
                }
                if(aggregationBuilder != null){
                    allAggregationBuilder.subAggregation(aggregationBuilder);
                }

            }

        }


    }

    private static BucketScriptPipelineAggregationBuilder getBucketScript(String aggName, Map<String, Object> aggParam){
        Map<String, String> bucketsPathHashMap = (Map<String, String>) aggParam.get("buckets_path");
        return PipelineAggregatorBuilders.bucketScript(aggName, bucketsPathHashMap,
                new Script(MapUtils.getString(aggParam,"script")));
    }

	/**
     *  根据聚合类型 获取对应的聚合builder
     * @param aggName  聚合名称
     * @param aggType  聚合类型
     * @param aggParam  聚合参数
     * @return AggregationBuilder
     */
    private static AggregationBuilder setAggsBuilders(String aggName, String aggType,  Map<String, Object> aggParam){

        String fieldValue = MapUtils.getString(aggParam, "field");

        AggregationBuilder aggregationBuilder = null;
        if("terms".equals(aggType)){
            int size = MapUtils.getIntValue(aggParam, "size");
            if(size == NumberUtils.INTEGER_ZERO){
                size = 10;
            }
            aggregationBuilder = AggregationBuilders.terms(aggName).field(fieldValue).size(size);
        }else if("sum".equals(aggType)){
            aggregationBuilder = AggregationBuilders.sum(aggName).field(fieldValue);
        }else if("avg".equals(aggType)){
            aggregationBuilder = AggregationBuilders.avg(aggName).field(fieldValue);
        }else if("max".equals(aggType)){
            aggregationBuilder = AggregationBuilders.max(aggName).field(fieldValue);
        }else if("min".equals(aggType)){
            aggregationBuilder = AggregationBuilders.min(aggName).field(fieldValue);
        }else if("value_count".equals(aggType)){
            aggregationBuilder = AggregationBuilders.count(aggName).field(fieldValue);
        }else if ("cardinality".equals(aggType)) {// 去重之后总数
            aggregationBuilder = AggregationBuilders.cardinality(aggName).field(fieldValue);
        } else if ("histogram".equals(aggType)) {// 直方图
            Double interval = MapUtils.getDouble(aggParam, "interval");
            Long minDocCount = MapUtils.getLong(aggParam, "min_doc_count");
            aggregationBuilder = AggregationBuilders.histogram(aggName).field(fieldValue).interval(interval)
                    .minDocCount(minDocCount);
        } else if ("date_histogram".equals(aggType)) {// 日期直方图
            String interval = MapUtils.getString(aggParam, "interval");
            String format = MapUtils.getString(aggParam, "format");
            Long minDocCount = MapUtils.getLong(aggParam, "min_doc_count");
            DateHistogramAggregationBuilder dateHistogramAggregationBuilder = AggregationBuilders.dateHistogram(aggName)
                    .field(fieldValue).dateHistogramInterval(new DateHistogramInterval(interval))
                    .minDocCount(minDocCount).timeZone(DateTimeZone.forOffsetHours(8));
            if (StringUtils.isNotEmpty(format)) {
                dateHistogramAggregationBuilder.format(format);
            }
            aggregationBuilder = dateHistogramAggregationBuilder;
        } else if ("range".equals(aggType)) {// 范围
            String fieleName = MapUtils.getString(aggParam, "field");
            List<Map<String, Object>> ranges = (List<Map<String, Object>>) aggParam.get("ranges");
            RangeAggregationBuilder rangeAggregationBuilder = AggregationBuilders.range(aggName).field(fieleName);
            ListUtils.emptyIfNull(ranges).forEach(e -> {
                Double from = MapUtils.getDouble(e, "from");
                Double to = MapUtils.getDouble(e, "to");
                rangeAggregationBuilder.addRange(from, to);
            });

            aggregationBuilder = rangeAggregationBuilder;
        } else if ("date_range".equals(aggType)) {// 日期范围
            String fieleName = MapUtils.getString(aggParam, "field");
            String format = MapUtils.getString(aggParam, "format");
            List<Map<String, Object>> ranges = (List<Map<String, Object>>) aggParam.get("ranges");
            DateRangeAggregationBuilder dateRangeAggregationBuilder = AggregationBuilders.dateRange(aggName)
                    .field(fieleName).timeZone(DateTimeZone.forOffsetHours(8));

            if (StringUtils.isNotEmpty(format)) {
                dateRangeAggregationBuilder.format(format);
            }
            ListUtils.emptyIfNull(ranges).forEach(e -> {
                String from = MapUtils.getString(e, "from");
                String to = MapUtils.getString(e, "to");
                dateRangeAggregationBuilder.addRange(from, to);
            });
            aggregationBuilder = dateRangeAggregationBuilder;
        }
        return aggregationBuilder;
    }


}

2,模拟数据

 private static Map<String,Object> initFirstData(){
        String data ="{\n" +
                "\t\"size\": 0,\n" +
                "\t\"aggs\": {\n" +
                "\t\t\"colors\": {\n" +
                "\t\t\t\"terms\": {\n" +
                "\t\t\t\t\"field\": \"color.keyword\"\n" +
                "\t\t\t},\n" +
                "\t\t\t\"aggs\": {\n" +
                "\t\t\t\t\"min_price\": {\n" +
                "\t\t\t\t\t\"value_count\": {\n" +
                "\t\t\t\t\t\t\"field\": \"material.keyword\"\n" +
                "\t\t\t\t\t}\n" +
                "\t\t\t\t},\n" +
                "\t\t\t\t\"max_price\": {\n" +
                "\t\t\t\t\t\"sum\": {\n" +
                "\t\t\t\t\t\t\"field\": \"price\"\n" +
                "\t\t\t\t\t}\n" +
                "\t\t\t\t},\n" +
                "\t\t\t\t\"gap_price\": {\n" +
                "\t\t\t\t\t\"bucket_script\": {\n" +
                "\t\t\t\t\t\t\"buckets_path\": {\n" +
                "\t\t\t\t\t\t\t\"deal0\": \"max_price\",\n" +
                "\t\t\t\t\t\t\t\"deal1\": \"min_price\"\n" +
                "\t\t\t\t\t\t},\n" +
                "\t\t\t\t\t\t\"script\": \"params.deal0 - params.deal1\"\n" +
                "\t\t\t\t\t}\n" +
                "\t\t\t\t}\n" +
                "\t\t\t}\n" +
                "\t\t}\n" +
                "\t}\n" +
                "}";
        System.out.println(JSONObject.parseObject(data).toJSONString());
        Map<String,Object> parse = (Map<String, Object>) JSON.parse(data);
        return parse;
    }

 

3,测试:

 

 public static void main(String[] args) {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        Map<String,Object> aggsMap = initFirstData();
        joinEsStrAggs(aggsMap, searchSourceBuilder);
        System.out.println("aggs "+searchSourceBuilder.toString());

    }

结果:

aggs  {
	"aggregations": {
		"colors": {
			"terms": {
				"field": "color.keyword",
				"size": 10,
				"min_doc_count": 1,
				"shard_min_doc_count": 0,
				"show_term_doc_count_error": false,
				"order": [{
					"_count": "desc"
				}, {
					"_key": "asc"
				}]
			},
			"aggregations": {
				"max_price": {
					"sum": {
						"field": "price"
					}
				},
				"min_price": {
					"value_count": {
						"field": "material.keyword"
					}
				},
				"gap_price": {
					"bucket_script": {
						"buckets_path": {
							"deal0": "max_price",
							"deal1": "min_price"
						},
						"script": {
							"source": "params.deal0 - params.deal1",
							"lang": "painless"
						},
						"gap_policy": "skip"
					}
				}
			}
		}
	}
}

总结:

    使用RestHighLevelClient 查询es聚合数据,处理参数会麻烦些,需要拼接对应的AggregationBuilder的内容,嵌套的,要逐层处理。复杂的东西,先从简单的入手,逐层解析,到后面就会发现规律的,有时候初看,知道有规律,但是又说不出来,那就动手实践。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天狼1222

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值