• Elasticsearch通过Http请求实现聚合分组及聚合计算查询


      😊 @ 作者: 一恍过去
      🎊 @ 社区: Java技术栈交流
      🎉 @ 主题: Elasticsearch通过Http请求实现聚合分组及聚合计算查询
      ⏱️ @ 创作时间: 2022年08月19日

      1、数据准备

      新增索引:

      # 新增索引
      PUT http://192.168.80.121:9200/cars
      
      # 请求参数
      {
        "settings": {
          "number_of_shards": 2,
          "number_of_replicas": 1
        },
        "mappings": {
            "properties": {
              "color": {
                "type": "keyword"
              },
              "make": {
                "type": "keyword"
              },
              "price": {
                "type": "float"
              },
                "sold": {
                "type": "keyword"
              }
            }
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26

      批量新增数:

      参考:《使用Http请求实现数据的批量导入

      # 批量导入数
      POST http://192.168.80.121:9200/cars/_bulk
      
      # 注意:必须换行
      
      {"index": {"_index": "cars", "_type": "_doc", "_id": 1}}
      { "price" : 10000, "color" : "red", "make" : "honda", "sold" : "2022-10-28" }
      
      {"index": {"_index": "cars", "_type": "_doc", "_id": 2}}
      { "price" : 20000, "color" : "red", "make" : "honda", "sold" : "2022-11-05" }
      
      {"index": {"_index": "cars", "_type": "_doc", "_id": 3}}
      { "price" : 30000, "color" : "green", "make" : "ford", "sold" : "2022-05-18" }
      
      {"index": {"_index": "cars", "_type": "_doc", "_id": 4}}
      { "price" : 15000, "color" : "blue", "make" : "toyota", "sold" : "2022-07-02" }
      
      {"index": {"_index": "cars", "_type": "_doc", "_id": 5}}
      { "price" : 12000, "color" : "green", "make" : "toyota", "sold" : "2022-08-19" }
      
      {"index": {"_index": "cars", "_type": "_doc", "_id": 6}}
      { "price" : 20000, "color" : "red", "make" : "honda", "sold" : "2022-11-05" }
      
      {"index": {"_index": "cars", "_type": "_doc", "_id": 7}}
      { "price" : 80000, "color" : "red", "make" : "bmw", "sold" : "2022-01-01" }
      
      {"index": {"_index": "cars", "_type": "_doc", "_id": 8}}
      { "price" : 25000, "color" : "blue", "make" : "ford", "sold" : "2022-02-12" }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29

      验证数据:

      # 验证
      GET http://192.168.80.121:9200/cars/_search
      
      • 1
      • 2

      2、 基本概念

      注意在ES中,需要进行聚合、排序、过滤的字段其处理方式比较特殊,因此不能被分词,设置文本类型为keyword。

      基本数据格式如下

      Elasticsearch中的聚合,包含多种类型,最常用的两种,一个叫,一个叫指标(度量):

      桶(bucket)

      桶的作用,是按照某种方式对数据进行分组(group by),每一组数据在ES中称为一个

      度量(metrics)

      分组完成以后,我们一般会对组中的数据进行聚合运算,例如求平均值、最大、最小、求和等,这些在ES中称为度量

      比较常用的一些度量聚合方式:

      • avg :求平均值
      • max :求最大值
      • min :求最小值
      • percentiles :求百分比
      • stats :同时返回avg、max、min、sum、count等
      • sum :求和
      • Top hits :求前几
      • Count:求总数

      3、 聚合为桶(分组查询)

      首先,我们按照 汽车的颜色color来划分

      # 请求:GET http://192.168.80.121:9200/cars/_search
      
      # 请求参数
      {
          # 查询条件可不要
         "query": {
          "range": {
            "price": {
              "gte": 1,
              "lt": 20000
            }
           }
          },
          "size" : 0,
          # 聚合处理
          "aggs" : {
              "popular_colors" : { 
                  "terms" : { 
                    # 分组字段
                    "field" : "color",
      			  # 排序操作(非必须)
                    "order": {
                       "_key": "desc", #根据返回分组名称排序
                      "_count": "desc" #根据返回数量排序
                     }
                  }
              }
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29

      请求参数说明:

      • size: 查询条数,这里设置为0,因为我们不关心搜索到的数据,只关心聚合结果,所以忽略hits中返回的数据提高效率。
        如果需要展示查看结果,可以设置指定值或者不设置(查询所有)
      • query:查询条件,只对满足查询条件的数据进行分组查询
      • aggs:声明这是一个聚合查询,是aggregations的缩写
        • popular_colors:给这次聚合起一个名字,任意。
          • terms:划分桶的方式,这里是根据词条划分
          • field:划分桶的字段
          • order:对分组结果设置排序,可用根据分组名称、返回数量进行排序,

      结果:

      {
        "took": 1,
        "timed_out": false,
        "_shards": {
          "total": 1,
          "successful": 1,
          "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": "red",
                "doc_count": 4
              },
              {
                "key": "blue",
                "doc_count": 2
              },
              {
                "key": "green",
                "doc_count": 2
              }
            ]
          }
        }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35

      响应参数说明:

      • hits:查询结果为空,因为查询时设置了size为0
      • aggregations:聚合的结果
      • popular_colors:我们定义的聚合名称
      • buckets:查找到的桶,每个不同的color字段值都会形成一个桶(分组)
        • key:这个桶对应的color字段的值
        • doc_count:这个桶(分组)中的文档数量

      4、 聚合指标(聚合计算)

      聚合指标是指直接对所有数据进行聚合,不进行分组查询;聚合方式为:avg、max、min、sum 、stats 、percentiles

      # 请求:GET http://192.168.80.121:9200/cars/_search
      
      # 请求参数,比如计算`price`的平均值
      {
          "size" : 0,
          "aggs":{
              "priceAggs": { 
                  "avg": {
                     "field": "price" 
                  }
              }
          }
      }
      
      #响应
      {
          "took": 2,
          "timed_out": false,
          "_shards": {
              "total": 2,
              "successful": 2,
              "skipped": 0,
              "failed": 0
          },
          "hits": {
              "total": {
                  "value": 8,
                  "relation": "eq"
              },
              "max_score": null,
              "hits": []
          },
          "aggregations": {
              "avg_price": {
                  "value": 26500.0
              }
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38

      5、桶内指标(分组聚合计算)

      是指对某个字段进行分组后再进行聚合计算;聚合方式为:avg、max、min、sum 、stats 、percentiles


      # 请求:GET http://192.168.80.121:9200/cars/_search
      
      # 请求参数,统计各个汽车颜色的平均价格
      {
          "size" : 0,
          "aggs" : { 
              "popularColors" : { 
                  "terms" : {
                    "field" : "color"
                  },
                  "aggs":{
                      "priceAggs": { 
                         "avg": {
                            "field": "price" 
                         }
                      }
                  }
              }
          }
      }
      
      
      # 结果
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24

      请求参数说明:

      • popularColors{}:聚合为桶的名称
      • aggs:设置聚合计算
        • priceAggs:度量聚合的名称
        • avg:度量的类型,这里是求平均值
        • field:度量运算的字段

      响应结果:

      {
          "took": 2,
          "timed_out": false,
          "_shards": {
              "total": 2,
              "successful": 2,
              "skipped": 0,
              "failed": 0
          },
          "hits": {
              "total": {
                  "value": 8,
                  "relation": "eq"
              },
              "max_score": null,
              "hits": []
          },
          "aggregations": {
              "populaColors": {
                  "doc_count_error_upper_bound": 0,
                  "sum_other_doc_count": 0,
                  "buckets": [
                      {
                          "key": "red",
                          "doc_count": 4,
                          "priceAggs": {
                              "value": 32500.0
                          }
                      },
                      {
                          "key": "blue",
                          "doc_count": 2,
                          "priceAggs": {
                              "value": 20000.0
                          }
                      },
                      {
                          "key": "green",
                          "doc_count": 2,
                          "priceAggs": {
                              "value": 21000.0
                          }
                      }
                  ]
              }
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47

      可以看到每个桶中都有自己的priceAggs字段,这是度量聚合(分组聚合计算)的结果

      6、 桶内嵌套桶

      桶不仅可以嵌套运算, 还可以再嵌套其它桶。也就是说在每个分组中,再分更多组。

      # 请求:GET http://192.168.80.121:9200/cars/_search
      
      # 请求参数,比如:统计每种颜色的汽车中,分别属于哪些制造商,按照`make`字段再进行分桶
      {
          "size" : 0,
          "aggs" : { 
              "popularColors" : { 
                  "terms" : { 
                    "field" : "color"
                  },
                  "aggs":{
                      "avgPrice": { 
                         "avg": {
                            "field": "price" 
                         }
                      },
                      "subMaker":{
                          "terms":{
                              "field":"make"
                          }
                      }
                  }
              }
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 原来的color桶和avg计算我们不变
      • subMaker:在嵌套的aggs聚合结果下新添一个桶,叫做subMaker
      • terms:桶的划分类型依然是词条
      • filed:这里根据make字段进行划分

      响应结果:

      {
          "aggregations": {
              "popularColors": {
                  "buckets": [
                      {
                          "key": "red",
                          "doc_count": 4,
                          "subMaker": {
                              "doc_count_error_upper_bound": 0,
                              "sum_other_doc_count": 0,
                              "buckets": [
                                  {
                                      "key": "honda",
                                      "doc_count": 3
                                  },
                                  {
                                      "key": "bmw",
                                      "doc_count": 1
                                  }
                              ]
                          },
                          "avgPrice": {
                              "value": 32500.0
                          }
                      },
                      {
                          "key": "blue",
                          "doc_count": 2,
                          "subMaker": {
                              "doc_count_error_upper_bound": 0,
                              "sum_other_doc_count": 0,
                              "buckets": [
                                  {
                                      "key": "ford",
                                      "doc_count": 1
                                  },
                                  {
                                      "key": "toyota",
                                      "doc_count": 1
                                  }
                              ]
                          },
                          "avgPrice": {
                              "value": 20000.0
                          }
                      },
                      {
                          "key": "green",
                          "doc_count": 2,
                          "subMaker": {
                              "doc_count_error_upper_bound": 0,
                              "sum_other_doc_count": 0,
                              "buckets": [
                                  {
                                      "key": "ford",
                                      "doc_count": 1
                                  },
                                  {
                                      "key": "toyota",
                                      "doc_count": 1
                                  }
                              ]
                          },
                          "avgPrice": {
                              "value": 21000.0
                          }
                      }
                  ]
              }
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71

      可以看到,新的聚合subMaker被嵌套在原来每一个color的桶中,如下图:
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t59RzUNb-1660574842886)(images/image-20220815222821845.png)]

    • 相关阅读:
      小公司招聘程序员要求985研究生,网友:这点钱,专科都不去
      CSRF及SSRF详解
      软考中级软件设计师--3.知识产权
      项目管理(影响项目的项目环境和管理过程)
      networkx学习记录
      2022-2027年中国劳动防护眼镜行业市场供需现状与趋势预测研究报告
      Qt | 内容边距(ContentsMargins)、间距(spacing)和 QSpacerItem 类
      基于javaweb+mysql数据库实现的学生选课管理系统项目源代码
      【Python基础篇016】异常处理的超详细讲解
      Java快速排序算法、三路快排(Java算法和数据结构总结笔记)[7/20]
    • 原文地址:https://blog.csdn.net/zhuocailing3390/article/details/126356288