袁庭新ES系列13节 | 聚合aggregations

287 阅读6分钟

前言

上一章节我们带领大家学习了Elasticsearch中的高级查询,这一章节袁老师再带领大家学习一种高级查询:聚合。

聚合可以用来干什么呢?聚合可以让我们极其方便的实现对数据的统计和分析。例如:

  • 什么品牌的手机最受欢迎?
  • 这些手机的平均价格、最高价格、最低价格?
  • 这些手机每月的销售情况如何?

实现这些统计功能的比数据库的SQL要方便的多,而且查询速度非常快,可以实现近实时搜索效果。

一. 基本概念

1.聚合基本概念介绍

Elasticsearch中的聚合,包含多种类型,最常用的两种:一个叫桶,一个叫度量。

桶(bucket)类似于(group by)。桶的作用是,按照某种方式对数据进行分组,每一组数据在Elasticsearch中称为一个桶 ,例如我们根据国籍对人划分,可以得到中国桶、英国桶、日本桶等;或者我们按照年龄段对人进行划分,010岁、1020岁、2030岁和3040岁等。

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进行集群相关的知识。

今天的内容就分享到这里吧。关注「袁庭新」,干货天天都不断!