ElasticSearchDSL查询模板之二(二重聚合)

本文介绍了如何在ElasticSearch中实现复杂的查询需求,包括在聚合基础上的二次聚类,以满足如查看特定日期类别销售数据等业务场景。同时推荐使用Postman工具来模拟HTTP请求,调试查询JSON。文中还提到了排序方式,如设置为'asc'即可实现升序排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值