深入理解Elasticsearch Pipeline聚集(2)
在前文中我们讨论管道聚集的结构,带你学习了几个典型的管道聚集类型:导数、累加求和等。
本文我们继续讨论管道聚集分析,主要包括统计、移动平均、移动函数、百分位、分组排序以及分组脚本等。示例数据仍然使用上文中的数据,这里不再说明。
1. 统计管道聚集
在度量聚集中,统计聚集计算索引中数值类型的统计指标,包括最小、最大、平均、求和以及次数。elasticsearch也提供了对其他聚集产生的分组计算统计指标,当stats聚合所需的值必须首先使用其他聚集计算产生每个分组时,则需要使用统计管道聚集。请看示例:
GET /traffic_stats/_search
{
"aggs" : {
"visits_per_month" : {
"date_histogram" : {
"field" : "date",
"interval" : "month"
},
"aggs": {
"total_visits": {
"sum": {
"field": "visits"
}
}
}
},
"stats_monthly_visits": {
"stats_bucket": {
"buckets_path": "visits_per_month>total_visits"
}
}
}
}
这个查询首先生成日期直方图,计算所有月份的访问量,生成多个分组;接下来使用stats
管道聚集计算这些分组的统计指标,响应结果如下:
{
"took" : 120,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 27,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"visits_per_month" : {
"buckets" : [
{
"key_as_string" : "2018-10-01T00:00:00.000Z",
"key" : 1538352000000,
"doc_count" : 3,
"total_visits" : {
"value" : 2060.0
}
},
{
"key_as_string" : "2018-11-01T00:00:00.000Z",
"key" : 1541030400000,
"doc_count" : 3,
"total_visits" : {
"value" : 2141.0
}
},
{
"key_as_string" : "2018-12-01T00:00:00.000Z",
"key" : 1543622400000,
"doc_count" : 3,
"total_visits" : {
"value" : 2949.0
}
},
{
"key_as_string" : "2019-01-01T00:00:00.000Z",
"key" : 1546300800000,
"doc_count" : 2,
"total_visits" : {
"value" : 1844.0
}
},
{
"key_as_string" : "2019-02-01T00:00:00.000Z",
"key" : 1548979200000,
"doc_count" : 2,
"total_visits" : {
"value" : 2411.0
}
},
{
"key_as_string" : "2019-03-01T00:00:00.000Z",
"key" : 1551398400000,
"doc_count" : 2,
"total_visits" : {
"value" : 3103.0
}
},
{
"key_as_string" : "2019-04-01T00:00:00.000Z",
"key" : 1554076800000,
"doc_count" : 2,
"total_visits" : {
"value" : 2639.0
}
},
{
"key_as_string" : "2019-05-01T00:00:00.000Z",
"key" : 1556668800000,
"doc_count" : 2,
"total_visits" : {
"value" : 2212.0
}
},
{
"key_as_string" : "2019-06-01T00:00:00.000Z",
"key" : 1559347200000,
"doc_count" : 2,
"total_visits" : {
"value" : 2661.0
}
},
{
"key_as_string" : "2019-07-01T00:00:00.000Z",
"key" : 1561939200000,
"doc_count" : 2,
"total_visits" : {
"value" : 2887.0
}
},
{
"key_as_string" : "2019-08-01T00:00:00.000Z",
"key" : 1564617600000,
"doc_count" : 2,
"total_visits" : {
"value" : 2966.0
}
},
{
"key_as_string" : "2019-09-01T00:00:00.000Z",
"key" : 1567296000000,
"doc_count" : 2,
"total_visits" : {
"value" : 3121.0
}
}
]
},
"stats_monthly_visits" : {
"count" : 12,
"min" : 1844.0,
"max" : 3121.0,
"avg" : 2582.8333333333335,
"sum" : 30994.0
}
}
}
统计管道聚集执行对日期直方图的每个分组计算各个统计指标,并附加在响应结果的后面。
对于扩展统计聚集逻辑一样,只是返回一些额外指标,如方差、标准差、平方和等,稍微调整下上面的示例使用扩展统计:
GET /traffic_stats/_search?size=0
{
"aggs" : {
"visits_per_month" : {
"date_histogram" : {
"field" : "date",
"interval" : "month"
},
"aggs": {
"total_visits": {
"sum": {
"field": "visits"
}
}
}
},
"stats_monthly_visits": {
"extended_stats_bucket": {
"buckets_path": "visits_per_month>total_visits"
}
}
}
}
响应结果只是最后增加几项指标:
"stats_monthly_visits" : {
"count" : 12,
"min" : 1844.0,
"max" : 3121.0,
"avg" : 2582.8333333333335,
"sum" : 30994.0,
"sum_of_squares" : 8.21767E7,
"variance" : 177030.30555555597,
"std_deviation" : 420.7496946588981,
"std_deviation_bounds" : {
"upper" : 3424.3327226511296,
"lower" : 1741.3339440155373
}
}
2. 百分位分组聚集
百分位统计指标表示有多少值落入百分位内,如:第65百分位是65%的观测值位于该值以下。
简单百分位度量聚集计算索引中数值类型字段对于百分位。
一些场景中使用如日期直方图生成分组,然后对这些分组产生的值应用百分位统计。这种情况下即可以基于父聚集也可以基于兄弟聚集计算百分位统计。请看示例:
GET /traffic_stats/_search?size=0
{
"aggs" : {
"visits_per_month" : {
"date_histogram" : {
"field" : "date",
"interval" : "month"
},
"aggs": {
"percentiles_monthly_visits": {
"percentiles": {
"field": "visits",
"percents": [ 15.0, 50.0, 75.0, 99.0 ]
}
}
}
}
}
}
这时直接对日期分组内中每个中文档进行百分位计算。下面另一个示例先对每个日期分组求和,在对这些分组和计算百分位:
GET /traffic_stats/_search?size=0
{
"aggs" : {
"visits_per_month" : {
"date_histogram" : {
"field" : "date",
"interval" : "month"
},
"aggs": {
"total_visits": {
"sum": {
"field": "visits"
}
}
}
},
"percentiles_monthly_visits": {
"percentiles_bucket": {
"buckets_path": "visits_per_month>total_visits",
"percents": [ 15.0, 50.0, 75.0, 99.0 ]
}
}
}
}
与正常百分位统计类似,也可以设置一组百分位,这里设置了15th, 50th, 75th, 99th 四个。运行结果会在追加所有分组的百分位统计:
"percentiles_monthly_visits" : {
"values" : {
"15.0" : 2141.0,
"50.0" : 2661.0,
"75.0" : 2949.0,
"99.0" : 3121.0
}
}
通过结果可以看出所有月份中99%的访问量都在3121次以下。
3. 移动平均聚集
移动平均或滚动平均是一个计算技术,它构造完整数据集的一系列平均值子集。子集通常称为窗口大小。事实上,窗口大小表示每个迭代中数据的数量。在每个迭代中,算法计算窗口内所有数的平均值,然后向前滑动,排除前面子集的第一个数,包括下一个子集的第一个数。这种方法称为移动平均。
举例:给定[1, 5, 8, 23, 34, 28, 7, 23, 20, 19]
,我们可以计算简单移动平均,设定窗口为5:
- (1 + 5 + 8 + 23 + 34) / 5 = 14.2
- (5 + 8 + 23 + 34+ 28) / 5 = 19.6
- (8 + 23 + 34 + 28 + 7) / 5 = 20
- ……
移动平均通常用于时间序列数据,抹平短期波动、特出长期趋势。主要为了消除高频波动或随机噪声数据,避免低频趋势明显。
- 移动平均模型
moving_avg
聚集支持5中移动平均模型:simple, linear, exponentially weighted(ewma), holt-linear, holt-winters。这些模型在窗口值的加权方式上有所不同。
随着数据值离现在越远(即窗口从它们滑走),权重可能会变得不同。我们可以通过model
参数设置不同模型计算移动平均聚集。
下面章节我们主要讨论 simple, linear, and exponentially weighted (ewma) 三种常用模型,其他模型读者可参考官方文档。
3.1. 简单模型
simple
模型首先计算所有窗口内数据值之和,然后除以窗口大小。也就是说,该模型简单计算每个窗口数据集的算数平均数。
下面示例使用simple
模型,设置窗口大小为30.聚集将对日期直方图生成的分组计算移动平均。
GET /traffic_stats/_search?size=0
{
"aggs" : {
"visits_per_month" : {
"date_histogram" : {
"field" : "date",
"interval" : "month"
},
"aggs": {
"total_visits": {
"sum": {
"field": "visits"
}
},
"the_movavg":{
"moving_avg":{
"buckets_path": "total_visits",
"window" : 30,
"model" : "simple"
}
}
}
}
}
}
响应结果为:
"aggregations" : {
"visits_per_month" : {
"buckets" : [
...
{
"key_as_string" : "2019-08-01T00:00:00.000Z",
"key" : 1564617600000,
"doc_count" : 2,
"total_visits" : {
"value" : 2966.0
},
"the_movavg" : {
"value" : 2490.7
}
},
{
"key_as_string" : "2019-09-01T00:00:00.000Z",
"key" : 1567296000000,
"doc_count" : 2,
"total_visits" : {
"value" : 3121.0
},
"the_movavg" : {
"value" : 2533.909090909091
}
}
]
}
}
窗口大小能改变移动平均的结果。窗口大小较小时("window": 10
),将紧紧遵循原始数据,仅平滑小幅度波动。相反使用较大窗口("window": 100
)会平滑所有较高频波动,仅保留低频、长期趋势。它也倾向于比实际数据“滞后”很多。
3.2. 线性模型
该模型对序列中的数据点赋予不同的线性权值。所以旧数据值(即接近窗口开始点)对最终平均计算占比较少。.这种方法用于减少数据平均值背后的“滞后”,因为较早的数据点对最终结果的影响较小。
与简单模型类似,线性模型往往“滞后”于实际数据,虽然比简单模型程度更小。请看下面示例,使用窗口大小30:
GET /traffic_stats/_search?size=0
{
"aggs" : {
"visits_per_month" : {
"date_histogram" : {
"field" : "date",
"interval" : "month"
},
"aggs": {
"total_visits": {
"sum": {
"field": "visits"
}
},
"the_movavg":{
"moving_avg":{
"buckets_path": "total_visits",
"window" : 30,
"model" : "linear"
}
}
}
}
}
}
响应数据为:
"aggregations" : {
"visits_per_month" : {
"buckets" : [
{
"key_as_string" : "2019-08-01T00:00:00.000Z",
"key" : 1564617600000,
"doc_count" : 2,
"total_visits" : {
"value" : 2966.0
},
"the_movavg" : {
"value" : 2539.75
}
},
{
"key_as_string" : "2019-09-01T00:00:00.000Z",
"key" : 1567296000000,
"doc_count" : 2,
"total_visits" : {
"value" : 3121.0
},
"the_movavg" : {
"value" : 2609.731343283582
}
}
]
}
}
3.3. 指数模型
该模型与线性模型逻辑类似,除了对旧数据的权重按照指数递减————不是线性。旧数据的递减速度可以通过alpha
参数进行控制。alpha
较小权重递减慢,平滑性更好。相反alpha
较大使得权重递减更快,减少它们对移动平均线的影响。缺省alpha
值为0.3
,其值得范围是包括[0~1]
之间任何浮点数。
下面示例与上面类似,除了增加额外settings
设置alpha
:
GET /traffic_stats/_search?size=0
{
"aggs" : {
"visits_per_month" : {
"date_histogram" : {
"field" : "date",
"interval" : "month"
},
"aggs": {
"total_visits": {
"sum": {
"field": "visits"
}
},
"the_movavg":{
"moving_avg":{
"buckets_path": "total_visits",
"window" : 30,
"model" : "ewma",
"settings": {
"alpha": 0.5
}
}
}
}
}
}
}
生成响应结果为:
"aggregations" : {
"visits_per_month" : {
"buckets" : [
{
"key_as_string" : "2019-08-01T00:00:00.000Z",
"key" : 1564617600000,
"doc_count" : 2,
"total_visits" : {
"value" : 2966.0
},
"the_movavg" : {
"value" : 2718.958984375
}
},
{
"key_as_string" : "2019-09-01T00:00:00.000Z",
"key" : 1567296000000,
"doc_count" : 2,
"total_visits" : {
"value" : 3121.0
},
"the_movavg" : {
"value" : 2842.4794921875
}
}
]
}
}
3.4. 推断预测
有时基于当前数据的趋势进行预测。所有的移动平均模型都支持预测模型,尝试根据当前平滑的移动平均数来预测未来数据。依赖模型参数,这些预测可能准确也可以不准确。simple, linear 和 ewma
模型都产生平滑的预测,收敛于集合中最后一个值的平均值。
使用predict
参数指定需要预测几个数值附加在数据序列之后。这些预测将与你预测分组的时间间隔相同。请看示例:
GET /traffic_stats/_search?size=0
{
"aggs" : {
"visits_per_month" : {
"date_histogram" : {
"field" : "date",
"interval" : "month"
},
"aggs": {
"total_visits": {
"sum": {
"field": "visits"
}
},
"the_movavg":{
"moving_avg":{
"buckets_path": "total_visits",
"window" : 30,
"model" : "linear",
"predict" : 3
}
}
}
}
}
}
响应结果在分组列表后面增加三个预测结果:
"aggregations" : {
"visits_per_month" : {
"buckets" : [
...
{
"key_as_string" : "2019-10-01T00:00:00.000Z",
"key" : 1569888000000,
"doc_count" : 0,
"the_movavg" : {
"value" : 2687.3924050632913
}
},
{
"key_as_string" : "2019-11-01T00:00:00.000Z",
"key" : 1572566400000,
"doc_count" : 0,
"the_movavg" : {
"value" : 2687.3924050632913
}
},
{
"key_as_string" : "2019-12-01T00:00:00.000Z",
"key" : 1575158400000,
"doc_count" : 0,
"the_movavg" : {
"value" : 2687.3924050632913
}
}
]
}
}
太好了!我们预测网站未来三个月的数据访问量。我们看到预测值很“平稳”,三个月数值相同。如果您希望根据局部的或全局的稳定趋势进行推断,那么应该选择holt模型。
4. 移动函数聚集(6.4之后)
前节介绍的移动平均聚集在6.4之后已不建议使用,可以使用移动函数聚集代替。
与移动平均聚集一样,移动函数聚集也是对数据集的子集进行计算,在数据集上逐渐滑动窗口。但是移动函数可以指定自定义脚本在每个窗口数据上执行。elasticsearch内置提供了一些脚本,如min/max,移动平均等。请看移动函数聚集的标准定义:
{
"moving_fn": {
"buckets_path": "the_sum",
"window": 10,
"script": "MovingFunctions.min(values)"
}
}
我们看到定义了一个移动函数聚集在窗口大小为10的数据集上使用内置的min聚集脚本,需要注意的是moving_fn
聚集必须嵌入在histogram 或 date_histogram
聚集内。
GET /traffic_stats/_search?size=0
{
"aggs" : {
"visits_per_month" : {
"date_histogram" : {
"field" : "date",
"interval" : "month"
},
"aggs": {
"total_visits": {
"sum": {
"field": "visits"
}
},
"the_movfn": {
"moving_fn": {
"buckets_path": "total_visits",
"window": 10,
"script": "MovingFunctions.unweightedAvg(values)"
}
}
}
}
}
}
移动函数平均是total_visits
聚集的兄弟聚集,visits_per_month
的子聚集。上面示例实现simple
移动平均计算。
elasticsearch内置聚集脚本有:
- max()
- min()
- sum()
- stdDev()
- unweightedAvg()
- linearWeightedAvg()
- ewma()
- holt()
- holtWinters()
所有函数访问都需要通过MovingFunctions
命名空间,如:MovingFunctions.min()
。
5. 分组选择器聚集
有时根据条件过滤有日期直方图或其他聚集生成的分组。我们可以使用分组选择器聚集,它包括一段脚本决定哪个分组应该被输出。
指定的度量必须是数值型并且脚本必须返回布尔值。
下面示例首先计算每个月访问量之和,然后评估是否大于3000,符合条件则保留在结果集中,否则被过滤。
GET /traffic_stats/_search?size=0
{
"aggs" : {
"visits_per_month" : {
"date_histogram" : {
"field" : "date",
"interval" : "month"
},
"aggs": {
"total_visits": {
"sum": {
"field": "visits"
}
},
"visits_bucket_filter": {
"bucket_selector": {
"buckets_path": {
"total_visits": "total_visits"
},
"script": "params.total_visits > 3000"
}
}
}
}
}
}
结果仅保留两个符合规则的分组,响应结果:
{
"took" : 1646,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 27,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"visits_per_month" : {
"buckets" : [
{
"key_as_string" : "2019-03-01T00:00:00.000Z",
"key" : 1551398400000,
"doc_count" : 2,
"total_visits" : {
"value" : 3103.0
}
},
{
"key_as_string" : "2019-09-01T00:00:00.000Z",
"key" : 1567296000000,
"doc_count" : 2,
"total_visits" : {
"value" : 3121.0
}
}
]
}
}
}
6. 分组排序聚集
分组排序是父管道聚集,其针对父多个分组聚集(如日期直方图)返回的分组进行排序。可以指定多个字段进行排序,可以基于_key
、_count
或其子聚集。也能通过设置from
和size
参数删除一些分组结果。
下面我们对父日期直方图计算的total_visits
值进行排序。按照降序进行排序并返回第一页。
GET /traffic_stats/_search?size=0
{
"aggs" : {
"visits_per_month" : {
"date_histogram" : {
"field" : "date",
"interval" : "month"
},
"aggs": {
"total_visits": {
"sum": {
"field": "visits"
}
},
"visits_bucket_sort": {
"bucket_sort": {
"sort": [
{"total_visits": {"order": "desc"}}
],
"size": 5
}
}
}
}
}
}
响应结果为前5条:
{
"took" : 15,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 27,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"visits_per_month" : {
"buckets" : [
{
"key_as_string" : "2019-09-01T00:00:00.000Z",
"key" : 1567296000000,
"doc_count" : 2,
"total_visits" : {
"value" : 3121.0
}
},
{
"key_as_string" : "2019-03-01T00:00:00.000Z",
"key" : 1551398400000,
"doc_count" : 2,
"total_visits" : {
"value" : 3103.0
}
},
{
"key_as_string" : "2019-08-01T00:00:00.000Z",
"key" : 1564617600000,
"doc_count" : 2,
"total_visits" : {
"value" : 2966.0
}
},
{
"key_as_string" : "2018-12-01T00:00:00.000Z",
"key" : 1543622400000,
"doc_count" : 3,
"total_visits" : {
"value" : 2949.0
}
},
{
"key_as_string" : "2019-07-01T00:00:00.000Z",
"key" : 1561939200000,
"doc_count" : 2,
"total_visits" : {
"value" : 2887.0
}
}
]
}
}
}
也可以使用该聚集不进行任何排序并删除部分结果,仅需要使用from
、size
,不指定sort
参数。下面示例仅返回第二、三两个分组:
GET /traffic_stats/_search?size=0
{
"aggs" : {
"visits_per_month" : {
"date_histogram" : {
"field" : "date",
"interval" : "month"
},
"aggs": {
"total_visits": {
"sum": {
"field": "visits"
}
},
"visits_bucket_sort": {
"bucket_sort": {
"from": 2,
"size": 2
}
}
}
}
}
}
响应结果:
{
"took" : 5,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 27,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"visits_per_month" : {
"buckets" : [
{
"key_as_string" : "2018-12-01T00:00:00.000Z",
"key" : 1543622400000,
"doc_count" : 3,
"total_visits" : {
"value" : 2949.0
}
},
{
"key_as_string" : "2019-01-01T00:00:00.000Z",
"key" : 1546300800000,
"doc_count" : 2,
"total_visits" : {
"value" : 1844.0
}
}
]
}
}
}
还可以同时使用选择器和排序:
GET /traffic_stats/_search?size=0
{
"aggs" : {
"visits_per_month" : {
"date_histogram" : {
"field" : "date",
"interval" : "month"
},
"aggs": {
"total_visits": {
"sum": {
"field": "visits"
}
},
"visits_bucket_filter": {
"bucket_selector": {
"buckets_path": {
"total_visits": "total_visits"
},
"script": "params.total_visits > 3000"
}
},
"visits_bucket_sort": {
"bucket_sort": {
"from": 0,
"size": 2
}
}
}
}
}
}
7. 分组脚本聚集
父管道聚集对每个父级每个分组的度量值执行脚本进行计算。特定度量值必须是数值型,脚本也需返回数值类型。脚本可以是内联的,或在文件、索引中。
下面示例首先对日期直方图分组计算分组中的最大值和最小值,然后通过脚本实现最小值除以最大值计算每个分组中两者的比率:
GET /traffic_stats/_search?size=0
{
"aggs" : {
"visits_per_month" : {
"date_histogram" : {
"field" : "date",
"interval" : "month"
},
"aggs": {
"min_visits": {
"min": {
"field": "visits"
}
},
"max_visits": {
"max": {
"field":"visits"
}
},
"min_max_ratio": {
"bucket_script": {
"buckets_path": {
"min_visits": "min_visits",
"max_visits": "max_visits"
},
"script": "params.min_visits / params.max_visits"
}
}
}
}
}
}
聚集计算每个分组的min_max_ratio
,并附加在每个分组之后:
{
"took" : 170,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 27,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"visits_per_month" : {
"buckets" : [
{
"key_as_string" : "2018-10-01T00:00:00.000Z",
"key" : 1538352000000,
"doc_count" : 3,
"min_visits" : {
"value" : 488.0
},
"max_visits" : {
"value" : 789.0
},
"min_max_ratio" : {
"value" : 0.6185044359949303
}
},
{
"key_as_string" : "2018-11-01T00:00:00.000Z",
"key" : 1541030400000,
"doc_count" : 3,
"min_visits" : {
"value" : 394.0
},
"max_visits" : {
"value" : 1299.0
},
"min_max_ratio" : {
"value" : 0.30331023864511164
}
},
{
"key_as_string" : "2018-12-01T00:00:00.000Z",
"key" : 1543622400000,
"doc_count" : 3,
"min_visits" : {
"value" : 768.0
},
"max_visits" : {
"value" : 1194.0
},
"min_max_ratio" : {
"value" : 0.6432160804020101
}
},
{
"key_as_string" : "2019-01-01T00:00:00.000Z",
"key" : 1546300800000,
"doc_count" : 2,
"min_visits" : {
"value" : 872.0
},
"max_visits" : {
"value" : 972.0
},
"min_max_ratio" : {
"value" : 0.897119341563786
}
},
{
"key_as_string" : "2019-02-01T00:00:00.000Z",
"key" : 1548979200000,
"doc_count" : 2,
"min_visits" : {
"value" : 827.0
},
"max_visits" : {
"value" : 1584.0
},
"min_max_ratio" : {
"value" : 0.5220959595959596
}
},
{
"key_as_string" : "2019-03-01T00:00:00.000Z",
"key" : 1551398400000,
"doc_count" : 2,
"min_visits" : {
"value" : 1499.0
},
"max_visits" : {
"value" : 1604.0
},
"min_max_ratio" : {
"value" : 0.9345386533665836
}
},
{
"key_as_string" : "2019-04-01T00:00:00.000Z",
"key" : 1554076800000,
"doc_count" : 2,
"min_visits" : {
"value" : 1247.0
},
"max_visits" : {
"value" : 1392.0
},
"min_max_ratio" : {
"value" : 0.8958333333333334
}
},
{
"key_as_string" : "2019-05-01T00:00:00.000Z",
"key" : 1556668800000,
"doc_count" : 2,
"min_visits" : {
"value" : 984.0
},
"max_visits" : {
"value" : 1228.0
},
"min_max_ratio" : {
"value" : 0.8013029315960912
}
},
{
"key_as_string" : "2019-06-01T00:00:00.000Z",
"key" : 1559347200000,
"doc_count" : 2,
"min_visits" : {
"value" : 1238.0
},
"max_visits" : {
"value" : 1423.0
},
"min_max_ratio" : {
"value" : 0.8699929725931131
}
},
{
"key_as_string" : "2019-07-01T00:00:00.000Z",
"key" : 1561939200000,
"doc_count" : 2,
"min_visits" : {
"value" : 1388.0
},
"max_visits" : {
"value" : 1499.0
},
"min_max_ratio" : {
"value" : 0.9259506337558372
}
},
{
"key_as_string" : "2019-08-01T00:00:00.000Z",
"key" : 1564617600000,
"doc_count" : 2,
"min_visits" : {
"value" : 1443.0
},
"max_visits" : {
"value" : 1523.0
},
"min_max_ratio" : {
"value" : 0.9474720945502298
}
},
{
"key_as_string" : "2019-09-01T00:00:00.000Z",
"key" : 1567296000000,
"doc_count" : 2,
"min_visits" : {
"value" : 1534.0
},
"max_visits" : {
"value" : 1587.0
},
"min_max_ratio" : {
"value" : 0.9666036546943919
}
}
]
}
}
}
8. 总结
你真棒,两节都看完基本已经学完所有的管道聚集,管道聚集实现涉及中间值的复杂计算。你可以利用elasticsearch脚本对返回度量实现自定义编程逻辑。举例:可以评估如果分组匹配一定规则则计算自定义度量,不是缺省内置的逻辑,如最小/最大比率。
本文参考链接:https://blog.csdn.net/neweastsun/article/details/104435860