前一篇文章中分享了按日期聚合和按关键字聚类的方法,可以查询一段时期的所有数据中,每一天有多少数据,每一个类别有多少数据。但是实际应用之中,业务场景往往更加复杂,一般情况这种聚合都是不够的,例如需要看某一天某种类的销售数据,某个类别下所有所选日期的数据,这就需要在之前聚类的基础上进行二次聚类。另外推荐大家一个软件,postman,可以利用这个软件直接写json,模拟真实的http/https请求环境。
一、按聚类目标再次聚类AggrAggr
public static JsonObject aggrAggr(String host, String index, String type, String query, String timeField, long startAt, long endAt, String aggr1, String aggr2) { Map timeRange = new HashMap (); timeRange.put("gte", startAt); timeRange.put("lte", endAt); timeRange.put("format", "epoch_millis"); Map extendedBounds = new HashMap (); extendedBounds.put("min", startAt); extendedBounds.put("max", endAt); Map paramMap = new HashMap (); paramMap.put("query", query); paramMap.put("aggr1", aggr1); paramMap.put("aggr2", aggr2); paramMap.put("time_field", timeField); paramMap.put("time_range", timeRange); paramMap.put("extended_bounds", extendedBounds); String url = String.format(selectFormat, host, index, type); String template = FileUtil.stream2string(PropertiesUtil.getInputStream("aggr_aggr.json")); return JsonUtil.toJsonMap(ElasticSearchUtil.selectByTemplate(url, template, paramMap)); }
其中aggr_aggr.json处的json文件是
{ "size": 0, "query": { "filtered": { "query": { "query_string": { "query": @query, "analyze_wildcard": true } }, "filter": { "bool": { "must": [ { "range": { @time_field: @time_range } } ], "must_not": [] } } } }, "aggs": { @aggr1: { "terms": { "field": @aggr1, "size": 0, "order": { "_count": "desc" } }, "aggs": { @aggr2: { "terms": { "field": @aggr2, "size": 0, "order": { "_count": "desc" } } } } } } } 该方法可以把符合query的查询条件的所有数据按aggr1的类别进行聚类,再把所有聚类结果按照aggr2进行聚类,其中aggr1和aggr2都是ES的某些字段。 二、按日期聚类再聚类DateAggr public static JsonObject generalDateAggr(String host, String index, String type, String query, String timeZone, String timeField, long startAt, long endAt, String timeInterval, String aggr) { Map timeRange = new HashMap (); timeRange.put("gte", startAt); timeRange.put("lte", endAt); timeRange.put("format", "epoch_millis"); Map extendedBounds = new HashMap (); extendedBounds.put("min", startAt); extendedBounds.put("max", endAt); Map paramMap = new HashMap (); paramMap.put("query", query); paramMap.put("aggr", aggr); paramMap.put("time_field", timeField); paramMap.put("time_interval", timeInterval); paramMap.put("time_range", timeRange); paramMap.put("time_zone", timeZone); paramMap.put("extended_bounds", extendedBounds); String url = String.format(selectFormat, host, index, type); String template = FileUtil.stream2string(PropertiesUtil.getInputStream("date_aggr.json")); return JsonUtil.toJsonMap(ElasticSearchUtil.selectByTemplate(url, template, paramMap)); } 其中的date_aggr.json是 { "size": 0, "query": { "filtered": { "query": { "query_string": { "query": @query, "analyze_wildcard": true } }, "filter": { "bool": { "must": [ { "range": { @time_field: @time_range } } ], "must_not": [] } } } }, "aggs": { @time_field: { "date_histogram": { "field": @time_field, "time_zone": @time_zone, "interval": @time_interval, "extended_bounds": @extended_bounds }, "aggs": { @aggr: { "terms": { "field": @aggr, "size": 0, "order": { "_count": "desc" } } } } } } } 三、按目标聚类 由上面的方法就可以写出AggrDate方法了,可以查询每一个聚类的内容按日分割,在此就不做赘述了,也可以作为一个思考题,来考验一下大家四、order排序
在上面的json中的
"order": {
"_count": "desc" }表明我们需要按照倒序的排列方式进行排列,那么如果我们要正序排序怎么办?
"order": { "_count": "asc" } 即可