前言
上一章节我们带领大家学习了Elasticsearch中的高级查询,这一章节袁老师再带领大家学习一种高级查询:聚合。
聚合可以用来干什么呢?聚合可以让我们极其方便的实现对数据的统计和分析。例如:
- 什么品牌的手机最受欢迎?
- 这些手机的平均价格、最高价格、最低价格?
- 这些手机每月的销售情况如何?
实现这些统计功能的比数据库的SQL要方便的多,而且查询速度非常快,可以实现近实时搜索效果。
一. 基本概念
1.聚合基本概念介绍
Elasticsearch中的聚合,包含多种类型,最常用的两种:一个叫桶,一个叫度量。
桶(bucket)类似于(group by)。桶的作用是,按照某种方式对数据进行分组,每一组数据在Elasticsearch中称为一个桶 ,例如我们根据国籍对人划分,可以得到中国桶、英国桶、日本桶等;或者我们按照年龄段对人进行划分,0~10岁、10~20岁、20~30岁和30~40岁等。
Elasticsearch中提供的划分桶的方式有很多:
桶划分方式 | 描述 |
Date Histogram Aggregation | 根据日期阶梯分组,例如给定阶梯为周,会自动每周分为一组 |
Histogram Aggregation | 根据数值阶梯分组,与日期类似,需要知道分组的间隔(interval) |
Terms Aggregation | 根据词条内容分组,词条内容完全匹配的为一组 |
Range Aggregation | 数值和日期的范围分组,指定开始和结束,然后按段分组 |
综上所述,我们发现bucket aggregations只负责对数据进行分组,并不进行计算,因此bucket中往往会嵌套另一种聚合metrics aggregations,即度量。
度量(metrics)相当于聚合的结果。分组完成以后,我们一般会对组中的数据进行聚合运算,例如求平均值、最大、最小、求和等,这些在Elasticsearch中称为度量。
比较常用的一些度量聚合方式:
度量聚合方式 | 描述 |
Avg Aggregation | 求平均值 |
Max Aggregation | 求最大值 |
Min Aggregation | 求最小值 |
Percentiles Aggregation | 求百分比 |
Stats Aggregation | 同时返回avg、max、min、sum、count等 |
Sum Aggregation | 求和 |
Top hits Aggregation | 求前几 |
Value Count Aggregation | 求总数 |
2.聚合操作数据准备
为了测试聚合,我们先批量导入一些数据。
创建索引:
PUT /car
{
"mappings": {
"orders": {
"properties": {
"color": {
"type": "keyword"
},
"make": {
"type": "keyword"
}
}
}
}
}
响应结果:
注意:在Elasticsearch中,需要进行聚合、排序、过滤的字段其处理方式比较特殊,因此不能被分词,必须使用keyword或数值类型 。这里我们将color和make这两个文字类型的字段设置为keyword类型,这个类型不会被分词,将来就可以参与聚合。
导入数据,这里是采用批处理的API,大家直接复制到Kibana运行即可:
POST /car/orders/_bulk
{ "index": {}}
{ "price": 10000, "color": "红", "make": "本田", "sold": "2020-10-28" }
{ "index": {}}
{ "price": 20000, "color": "红", "make": "本田", "sold": "2020-11-05" }
{ "index": {}}
{ "price": 30000, "color": "绿", "make": "福特", "sold": "2020-05-18" }
{ "index": {}}
{ "price": 15000, "color": "蓝", "make": "丰田", "sold": "2020-07-02" }
{ "index": {}}
{ "price": 12000, "color": "绿", "make": "丰田", "sold": "2020-08-19" }
{ "index": {}}
{ "price": 20000, "color": "红", "make": "本田", "sold": "2020-11-05" }
{ "index": {}}
{ "price": 80000, "color": "红", "make": "宝马", "sold": "2020-01-01" }
{ "index": {}}
{ "price": 25000, "color": "蓝", "make": "福特", "sold": "2020-02-12" }
运行上述代码,响应结果:
二. 聚合为桶
1.聚合为桶语法介绍
首先,我们按照汽车的颜色color来划分桶,按照颜色分桶最好是使用Term Aggregation类型,按照颜色的名称来分桶。语法格式见下:
GET /索引库名称/_search
{
"size": 0,
"aggs": {
"popular_colors": {
"度量聚合方式": {
"field": "字段名称"
}
}
}
}
桶查询的相关属性介绍:
属性 | 描述 |
size | 查询条数,这里设置为0,因为我们不关心搜索到的数据,只关心聚合结果,提高效率 |
aggs | 声明这是一个聚合查询,是aggregations的缩写 |
popular_colors | 给这次聚合起一个名字,可任意指定(建议做到见名知意) |
terms | 聚合的类型,这里选择terms,是根据词条内容(这里是颜色)划分 |
field | 划分桶时依赖的字段 |
2.聚合为桶案例演示
根据汽车的颜色聚合为桶:
GET /car/_search
{
"size": 0,
"aggs": {
"popular_colors": {
"terms": {
"field": "color"
}
}
}
}
运行上述代码,响应结果:
{
"took": 93,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 8,
"max_score": 0,
"hits": []
},
"aggregations": {
"popular_colors": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "红",
"doc_count": 4
},
{
"key": "绿",
"doc_count": 2
},
{
"key": "蓝",
"doc_count": 2
}
]
}
}
}
输入的结果如下图所示:
桶查询响应结果的相关属性介绍:
属性 | 描述 |
hits | 查询结果为空,因为我们设置了size为0 |
aggregations | 聚合的结果 |
popular_colors | 我们定义的聚合名称 |
buckets | 查找到的桶,每个不同的color字段值都会形成一个桶 |
key | 这个桶对应的color字段的值 |
doc_count | 这个桶中的文档数量 |
通过聚合的结果我们发现,目前红色的小车比较畅销。
三. 桶内度量
1.桶内度量介绍
前面的例子告诉我们每个桶里面的文档数量,这很有用。 但通常,我们的应用需要提供更复杂的文档度量。 例如,每种颜色汽车的平均价格是多少?
因此,我们需要告诉Elasticsearch使用哪个字段,使用何种度量方式进行运算,这些信息要嵌套在桶内,度量的运算会基于桶内的文档进行。
桶内度量语法介绍:
GET /索引库名称/_search
{
"size": 0,
"aggs": {
"聚合名称": {
"度量聚合方式": {
"field": "字段名称"
},
"aggs": {
"聚合名称": {
"度量类型": {
"field": "字段名称"
}
}
}
}
}
}
2.桶内度量案例
现在,我们为刚刚的聚合结果添加求价格平均值的度量。
GET /car/_search
{
"size": 0,
"aggs": {
"popular_colors": {
"terms": {
"field": "color"
},
"aggs": {
"avg_price": {
"avg": {
"field": "price"
}
}
}
}
}
}
桶内度量相关属性介绍:
属性 | 描述 |
aggs | 我们在上一个aggs(popular_colors)中添加新的aggs。可见度量也是一个聚合 |
avg_price | 聚合的名称 |
avg | 度量的类型,这里是求平均值 |
field | 度量运算的字段 |
响应结果:
{
"took": 43,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 8,
"max_score": 0,
"hits": []
},
"aggregations": {
"popular_colors": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "红",
"doc_count": 4,
"avg_price": {
"value": 32500
}
},
{
"key": "绿",
"doc_count": 2,
"avg_price": {
"value": 21000
}
},
{
"key": "蓝",
"doc_count": 2,
"avg_price": {
"value": 20000
}
}
]
}
}
}
可以看到每个桶中都有自己的avg_price字段,这是度量聚合的结果。
四. 结语
好了关于Elasticsearch中的聚合aggregations查询相关的内容袁老师就给大家介绍到这里,这一章节我们主要学习了聚合的基本概念,例如桶和度量。然后,带领大家通过综合案例的形式学习了如何聚合为桶,以及如何在桶内进行度量操作。关于Elasticsearch的聚合相关内容我们就给大家介绍到这里。下一小节我们带领同学们学习如何使用Elasticsearch进行集群相关的知识。
今天的内容就分享到这里吧。关注「袁庭新」,干货天天都不断!