ElasticSearch桶、度量
桶
桶的作用,是按照某种方式对数据进行分组,每一组数据在ES中称为一个桶,例如我们根据国籍对人划分,可以得到中国桶、英国桶、日本桶,或者我们按照年龄段对人进行划分:0-10,10-20,20-30,30-40等
ElasticSearch中提供的划分桶的方式有很多
- 根据日期阶梯分组,例如给定阶梯为周,会自动每周分为一组
- 根据数值阶梯分组,与日期类似,需要知道分组的间隔
- 根据词条内容分组,词条内容完全匹配的为一组,类似数据库group by
- 数值和日期的范围分组,指定开始和结束,然后按段分组
综上所述,我们发现bucket aggregations只负责对数据进行分组,并不进行,并不进行计算,因此往往bucket中往往会嵌套另一种聚合
度量
分组完成之后,我们一般会对组中的数据进行聚合运算,例如求平均值、最大、最小、求和等,这些在ES中称为度量
比较常用的一些度量聚合方式
- 求平均值
- 求最大值
- 求最小值
- 求百度比
- 同时返回avg、max、min、sum、count
- 求和
- 求前几
- 求总数
聚合为桶
首先,我们按照汽车的颜色 color 来划分桶,按照颜色分桶,最好是使用 term aggregation 类型,按照颜色的名称来分桶
GET /car/_search { "size": 0, // 不需要展示文档数据 "aggs": { // 聚合分桶 "popular_colors": { // 自定义分桶的名称 "terms": { // 根据词条分桶 "field": "color" } } } }
- size:查询条数,这里设置为0,因为我们不关心搜索到的数据,只关心聚合结果,提高效率
- aggs:声明这是一个聚合查询,是 aggregations 的缩写
- popular_colors:给这次聚合起一个名字,可任意指定
- terms:聚合的类型,这里选择 terms,是根据词条内容(这里是颜色)划分
- field:划分桶时依赖的字段
- hits:查询结果为空,因为我们设置了 size 为0
- aggregations:聚合的结果
- popular_colors:我们定义的聚合名称
- buckets:查找到的桶,每个不同的 color 字段值都会形成一个桶
- key:这个桶对应的 color 字段的值
- doc_count:这个桶中的文档数量
通过聚合的结果我们发现,目前红色的小车比较畅销!
桶内度量
前面的例子告诉我们每个桶里面的文档数量,这很有用。但通常,我们的应用需要提供更复杂的文档度量。例如,每种颜色汽车的平均价格是多少?
因此,我们需要告诉 ElasticSearch 使用哪个字段,使用何种度量方式进行运算,这些信息要嵌套在桶内,度量的运算会基于桶内的文档进行
现在,我们为刚刚的聚合结果添加求价格平均值的度量
GET /car/_search { "size": 0, // 不需要展示文档数据 "aggs": { // 聚合分桶 "popular_colors": { // 自定义分桶的名称 "terms": { // 根据词条分桶 "field": "color" }, "aggs": { // 进一步分桶,统计桶内的数据信息 "avg_price": { // 自定义度量名称 "avg": { // 度量方式 "field": "price" } } } } } }
可以看到,每个桶中都有自己的 avg_price 字段,这是度量聚合的结果
桶内嵌套桶
上面的例子中,我们在桶内嵌套度量运算,事实上桶不仅可以嵌套运算,还可以再嵌套其他桶。也就是说在每个分组中,再分更多组。
比如,我们想要统计每种颜色的汽车中,分别属于哪个制造商,按照 make 字段再进行分桶
GET /car/_search { "size": 0, "aggs": { "popular_colors": { "terms": { "field": "color" }, "aggs": { "avg_price": { "avg": { "field": "price" } }, "maker": { "terms": { "field": "make" } } } } } }
- 原来的 color 桶和 avg 计算我们不变
- maker 在嵌套的 aggs 下新添一个桶,叫做 maker
- terms 桶的划分类型依然是词条
- filed 这里根据 make 字段进行划分
- 我们可以看到,新的聚合 maker 被嵌套在原来每一个 color 的桶中
- 每个颜色下面都根据 make 字段进行了分组
- 我们能读到的信息
- 红色车共有4辆
- 红色车的平均售价是32500
- 其中3辆是本田制造,1辆是宝马制造