前一篇文章中分享了按日期聚合和按关键字聚类的方法,可以查询一段时期的所有数据中,每一天有多少数据,每一个类别有多少数据。但是实际应用之中,业务场景往往更加复杂,一般情况这种聚合都是不够的,例如需要看某一天某种类的销售数据,某个类别下所有所选日期的数据,这就需要在之前聚类的基础上进行二次聚类。另外推荐大家一个软件,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"
}
即可