本文来说一个ES中极其重要的一个概念,就是聚合,聚合功能是一个十分方便的功能。

一、ES的聚合分析

1、什么是聚合(Aggregation)

1、ES除了文本搜索之外,提供了针对ES数据进行统计分析的功能

  • 实时性高
  • Hadoop有时候是T+1的实现,es的聚合做的比较好

2、通过聚合,我们会得到一个数据的概览,是分析和总结全套的数据,而不是寻找单个文档。

  • 比如查找大同和北京的酒店数量
  • 不同的价格区间,可以预定的经济型酒店和五星级酒店的数量

3、高性能,只需要一条1语句,就可以从es得到分析结果

  • 无需再客户端自己去聚合逻辑,全部交由ES服务端

2、聚合的使用场景

关于聚合,我们举几个例子来看看到底是干啥用的。
1、公司程序员的工作岗位分布
2、公司采用的编程框架分布
3、公司的薪资分布
4、客户的地理位置分布
5、订单的增长情况
我们可以看到,聚合其实就是对于一些分布的统计得到一些统筹的数据结果。

3、聚合的分类

1、Bucket Aggregation
索引中的那些列满足特定条件的文档的集合,类似于把满足条件的数据文档分在一个个的桶里面,这就能得到一个分布情况。

2、Metric Aggregation
一些数学运算,可以对文档字段进行统计非恩熙,比如得到最大值,最小值,平均值之类的。

3、Pipeline Aggregation
对于其他的聚合结果进行二次聚合。

4、Matrix Aggregation
支持对多个字段的操作,并且提供一个结果矩阵。

4、Bucket && Metric

翻译一下就是分组和统计。

我们可以结合着MYSQL中的一些概念,借助关系型数据库的思想更加符合人的思维。

java es 多聚合后统计数量 es数据聚合_全文检索

4.1、Bucket

翻译一下就是分桶,分组。把数据按照类别分组到一起,还支持二次分桶。

比如项目中的商品数据,我们可以根据价格分组为高档,中档,抵挡三组数据。

我们可以为之打分根据打分分为优质,中等,一般三种数据。

java es 多聚合后统计数量 es数据聚合_数据库_02


举个例子

从属关系:大同属于山西,

嵌套关系:大同属于山西,山西属于中国

ES还提供了很多类型的Bucket,帮助用多种方式划分文档。
比如Term & Range(时间,年龄区间,地理位置等等)

4.2、Metric

1、Metric是基于数据集计算结果,除了支持在字段上进行计算,同样也支持在脚本(painless script)产生的结果纸上进行计算。

2、大多数的Metric是数学计算,仅仅输出一个值
比如min / max / sum / avg / cardinality

3、部分Metric支持输出多个数值
比如stats输出平均,最大,最小
比如percentiles百分位,输出百分位点的分布,有点像普罗米修斯
比如percentiles_ranks

5、一个Bucket的例子

首先kibana_sample_data_flights索引是当时安装kibana的时候官方的数据导入的。这个索引里面存储这航班的一些信息数据。

5.1、查看航班目的地的统计信息

#按照目的地进行分桶统计
GET kibana_sample_data_flights/_search
{
	"size": 0,
	"aggs":{
		"flight_dest":{    分桶之后展示的别名,类似Mysql里面的as
			"terms":{  按照terms进行分桶
				"field":"DestCountry"航班目的地进行分组
			}
		}
	}
}
按照terms进行分桶就是按照文本,比如你名字叫张三,就叫张三的都在一个桶里面,最常见的分组,term在es中就是词汇的意思。

分桶结果如下:

"aggregations" : {
    "flight_dest" : {这就是那别名
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 3187,
      "buckets" : [
        {
          "key" : "IT",  去意大利的有2371趟航班
          "doc_count" : 2371
        },
        {
          "key" : "US",
          "doc_count" : 1987
        },
        {
          "key" : "CN",
          "doc_count" : 1096
        },
        {
          "key" : "CA",
          "doc_count" : 944
        },
        {
          "key" : "JP",
          "doc_count" : 774
        },
        {
          "key" : "RU",
          "doc_count" : 739
        },
        {
          "key" : "CH",
          "doc_count" : 691
        },
        {
          "key" : "GB",
          "doc_count" : 449
        },
        {
          "key" : "AU",
          "doc_count" : 416
        },
        {
          "key" : "PL",
          "doc_count" : 405
        }
      ]
    }
  }

这样就统计出了去往哪里的航班数,做了一个简单的分桶查询。

5.2、查看航班目的地的统计信息,增加平均,最高最低价格

我们上面按照航班目的地分组了,我们现在还想在目的地分组的基础上,增加均价,最高最低价格的分组结果。

GET kibana_sample_data_flights/_search
{
	"size": 0,
	"aggs":{  外层分组,按照目的地航班
		"flight_dest":{
			"terms":{
				"field":"DestCountry"
			},
			"aggs":{ 分组之上再加分组
				"avg_price":{ 取个别名
					"avg":{ 是取平均值
						"field":"AvgTicketPrice"
					}
				},
				"max_price":{
					"max":{ 取最大值
						"field":"AvgTicketPrice"
					}
				},
				"min_price":{
					"min":{ 取最小值
						"field":"AvgTicketPrice"
					}
				}
			}
		}
	}
}

上面语句的意思就是,先按照航班目的地分组,然后在每个分组内部,取得每个分组的平均值,最大值,最小值。
查询结果如下:

"aggregations" : {
    "flight_dest" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 3187,
      "buckets" : [
        {
          "key" : "IT", 去意大利的分组
          "doc_count" : 2371, 有2371趟航班
          "max_price" : { 去意大利最贵的机票价格
            "value" : 1195.3363037109375
          },
          "min_price" : {去意大利最便宜的几篇价格
            "value" : 100.57646942138672
          },
          "avg_price" : {去意大利平均机票价格
            "value" : 586.9627099618385
          }
        },
        {
          "key" : "JP",
          "doc_count" : 774,
          "max_price" : {
            "value" : 1199.4913330078125
          },
          "min_price" : {
            "value" : 103.97209930419922
          },
          "avg_price" : {
            "value" : 650.9203447346847
          }
        },
        {
          "key" : "RU",
          "doc_count" : 739,
          "max_price" : {
            "value" : 1196.7423095703125
          },
          "min_price" : {
            "value" : 101.0040054321289
          },
          "avg_price" : {
            "value" : 662.9949632162009
          }
        }
      ]
    }
  }

5.3、价格统计信息+天气信息

查看航班目的地的统计信息,平均票价,以及天气状况。

GET kibana_sample_data_flights/_search
{
	"size": 0,
	"aggs":{
		"flight_dest":{去别名
			"terms":{
				"field":"DestCountry"按照目的地的词汇分组
			},
			"aggs":{
				"stats_price":{取别名
					"stats":{ 这个救赎输出多个的结果的指标是多个metric
						"field":"AvgTicketPrice"
					}
				},
				"wather":{取别名
				  "terms": {
				    "field": "DestWeather",
				    "size": 5  只统计五个桶,也就是只显示分出五个类别,具体怎么取后面看
				  }
				}

			}
		}
	}
}

输出结果如下:

"aggregations" : {
    "flight_dest" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 3187,
      "buckets" : [
        {
          "key" : "US", 
          "doc_count" : 1987, 去美国的航班有1987个,下面是这1987个航班里面的天气分组
          "wather" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 438,
            "buckets" : [
              {
                "key" : "Rain", 下雨天的有371个,下面的都是晴天多云之类的,总共五个
                "doc_count" : 371
              },
              {
                "key" : "Clear",
                "doc_count" : 346
              },
              {
                "key" : "Sunny",
                "doc_count" : 345
              },
              {
                "key" : "Cloudy",
                "doc_count" : 330
              },
              {
                "key" : "Heavy Fog",
                "doc_count" : 157
              }
            ]
          },
          "stats_price" : {这个就是输出多个指标结果的
            "count" : 1987, 总共是1987个
            "min" : 100.14596557617188,  最小票价是
            "max" : 1199.72900390625,最大票价
            "avg" : 595.7743908825026,
            "sum" : 1183803.7146835327
          }
        },

bucket和metric都是聚合的种类。

二、总结

就是分组和统计,记得对应Mysql理解,然后多加使用。

顺便提一嘴,这就是京东的聚合。

java es 多聚合后统计数量 es数据聚合_大数据_03