Elasticsearch的聚合

本文深入探讨Elasticsearch中的聚合功能,解析bucket与metrics概念,演示如何使用aggs关键字进行基本聚合,嵌套聚合及聚合指标计算,适用于对大量数据进行高效过滤与统计分析。

一些概念

如同sql里面的group by关键字,Elasticsearch(以下简称es)也是支持聚合、统计的。

es的聚合有两个比较重要的概念:

  • bucket :桶
  • Metrics :指标

Buckets

Buckets简单来说就是满足特定条件的文档的集合。

如同我们经常使用的sql中group by A,B,C…,每个A,B,C等这样的关键字都可以将其视为桶。因为数据库的表都是二维表的形式,es的Buckets并不支持多个字段,但是可以嵌套。这个后续会说到。

Metrics

Metrics 就是对Buckets里面的数据进行各种统计计算。

如同sql里面group by后,你可以使用关键字count、max、avg等来统计,计算最大、最小、平均值。es当然也都支持,而且还有一些更多的sao操作,后续说到。

基本聚合

说明:关于对es的交互,可以先去翻翻我之前写的博文。这里不再累述,仅会给出查询表达式。后续皆是。

aggs关键字

aggs关键字使用规则比较简单:给聚合取个名,指定要聚合的关键字。比如:

{
  "size": 0,
  "aggs": {
    "srvNameAgg": {
      "terms": {
        "field": "srvName"
      }
    }
  }
}

这个就表示对srvName字段进行聚合,“size”:0表示不需要hits的结果。结果如下:

{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 10000,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "srvNameAgg": {
      "doc_count_error_upper_bound": 81,
      "sum_other_doc_count": 5633,
      "buckets": [
        {
          "key": "sDynSvc",
          "doc_count": 1514
        },
        {
          "key": "sAppQry",
          "doc_count": 518
        },
        ...

聚合的结果是在aggregations.你的聚合名.buckets里面。也可以看到。

嵌套聚合

正如之前所说的。es的聚合并支持多个字段的聚合,也就是说,你不能在一个aggs下多个字段聚合。
BUT,这个问题可以通过别的script方式实现,但是需要改下es原有的配置,有兴趣可以看看这个:https://www.elastic.co/guide/en/elasticsearch/reference/6.3/search-aggregations-metrics-scripted-metric-aggregation.html

其实,我们通过sql group by出来的结果,比如这种,聚合出来的二维表,
https://blog.abreaking.com/upload/2019/09/vftklp9uk0gujqv8f8g7c0qna8.jpg
我们同样可以通过Json节点的形式来进行描述:

{
  "DMDB":{
    "DRS":{
      "DMDB.DRS.DrSendType":"",
      "DMDB.DRS.ProcessExists":"",
    },
    "DRS.B":{
      "DMDB.DRS.B.DrSendType":"",
      "DMDB.DRS.B.ProcessExists":""
    },
    ...
  },
  "HBase":{
    "HMaster":{
      "Hadoop.HBase.HMaster.HaStatus":"",
      "Hadoop.HBase.HMaster.ProcessExists":""
    },
    "HRegionServer":{
      "Hadoop.HBase.HRegionServer.Blocked":"",
      "Hadoop.HBase.HRegionServer.ProcessExists":""
    }
    ...
  },
  "HDFS":{
    "DataNode":{
      "Hadoop.HDFS.DataNode.ProcessExists":""
    },
    "NameNode":{
      "Hadoop.HDFS.NameNode.HaStatus":"",
      "Hadoop.HDFS.NameNode.ProcessExists":""
    }
    ...
  },
  "YARN":{
    ...
  }
}

所以,针对这种多聚合,我们直接嵌套桶(buket)的方式。

{
  "size": 0,
  "aggs": {
    "srvNameAgg": {
      "terms": {
        "field": "srvName"
      },
      "aggs":{
        "retCodeAgg":{
          "terms":{
            "field":"retCode"
          },
          "aggs":{
            "retMsgAgg": {
              "terms": {
                "field": "retMsg"
              }
            }
          }
        }
      }
    }
  }
}

返回结果形如:

{
  ...,
  "aggregations": {
    "srvNameAgg": {
      "doc_count_error_upper_bound": 81,
      "sum_other_doc_count": 5633,
      "buckets": [
        {
          "key": "sPFeeQuery",
          "doc_count": 497,
          "retCodeAgg": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
              {
                "key": "0",
                "doc_count": 465,
                "retMsgAgg": {
                  "doc_count_error_upper_bound": 0,
                  "sum_other_doc_count": 0,
                  "buckets": [
                    {
                      "key": "ok!",
                      "doc_count": 465
                    }
                  ]
                }
              },
              {
                "key": "422001001",
                "doc_count": 32,
                "retMsgAgg": {
                  "doc_count_error_upper_bound": 0,
                  "sum_other_doc_count": 22,
                  "buckets": [
                    {
                      "key": "用户不存在 ERRID:10901775",
                      "doc_count": 1
                    },
                    {
                      "key": "用户不存在 ERRID:13251308",
                      "doc_count": 1
                    }
                  ]
                }
              }
            ]
          }
        },
        {
          "key": "sUserOrdQry",
          "doc_count": 360,
          "retCodeAgg": {
          ...

Tips:重点观察下buckets下面的key及doc_count

需要注意的是,经过本人的测试,聚合嵌套的越多效率也就越地低。尤其是某一层的桶可能返回数据特别多(比如后续说到的对时间粒度的聚合),聚合效率更是尤为低下。

聚合指标

从上面可以看出,es默认是返回了统计的结果,也就是类似数据库的count(*)的结果。它同样也是能支持avg、min、max等计算。

比如:求esb里面服务的平均执行时间:

{
  "size":0,
  "aggs":{
    "srv_aggs":{
      "terms":{
        "field":"srvName"

      },
      "aggs":{
        "avg_executeTime":{
          "avg":{
            "field":"executeTime"
          }
        }
      }
    }
  }
}

结果如下:

"took": 15,
   "timed_out": false,
   "_shards":    {...},
   "hits":    {...},
   "aggregations": {"srv_aggs":    {
      "doc_count_error_upper_bound": 49,
      "sum_other_doc_count": 2607,
      "buckets":       [
                   {
            "key": "sAppQry",
            "doc_count": 2440,
            "avg_executeTime": {"value": 107.825}
         },
                  {
            "key": "sPFeeQuery",
            "doc_count": 1483,
            "avg_executeTime": {"value": 219.701955495617}
         },
                  {
            "key": "sUserOrdQry",
            "doc_count": 1427,
            "avg_executeTime": {"value": 91.43587946741415}
         },
                  {
            "key": "sQryCreditInfo",
            "doc_count": 444,
            "avg_executeTime": {"value": 59.240990990990994}
         },
         ...

The end

聚合是比较费时间的。普通的查询,如term、match,都是通过倒排索引来匹配,其时间复杂度基本上可以视为o(1)。而聚合是会遍历所有的数据,时间复杂度则是o(n),随着多层的嵌套,其时间复杂度线性增长。

所以,最好不要对大量的数据进行聚合,尤其不要嵌套聚合。应该在聚合之前对这大量的数据先过滤,筛选出有意义的数据再进行聚合。

关于过滤+聚合可以参考后续博文。

Reference

官方文档—Aggregations:https://www.elastic.co/guide/en/elasticsearch/guide/current/aggregations.html

### 使用Elasticsearch聚合功能 #### 设置环境并执行基本聚合查询 为了利用Elasticsearch的强大聚合能力,首先需要确保已安装配置好Elasticsearch集群,并通过RESTful API接口与其交互。对于简单的聚合操作,比如基于单个字段进行统计汇总,可以直接构建`terms`类型的聚合查询。 ```json GET /es_db/_search { "size": 0, "aggs": { "hs_remark_agg": { "terms": { "field": "remark.keyword" } } } } ``` 上述命令展示了如何创建一个仅返回聚合结果而不展示具体文档详情的请求[^4]。这里设置了`size: 0`来指示服务器忽略具体的匹配项而专注于聚合部分的结果集处理。 #### 多字段复合聚合实现 当涉及到多个维度的同时分析时,则可采用更复杂的结构——即所谓的“桶内嵌套”。这允许在一个更大的分类下进一步细分数据点。例如,在测试案例中验证了多字段组合的有效性[^1]: ```json POST /your_index_name/_search?size=0 { "query": {}, "aggs": { "composite_aggregation_example": { "composite": { "sources": [ {"source_field_1": {"terms": {"field": "field_one"}}}, {"source_field_2": {"terms": {"field": "field_two"}}} ] } } } } ``` 这段JSON定义了一个名为`composite_aggregation_example`的新聚合器实例,其中包含了两个源字段作为分组依据。这种设计非常适合于探索不同属性之间的关系以及它们共同影响下的分布情况。 #### 应用场景举例说明 实际应用方面,Elasticsearch聚合特性广泛适用于各类数据分析需求。无论是追踪用户行为轨迹还是评估产品性能表现,亦或是研究人力资源状况等都能找到合适的解决方案[^2]。例如,可以通过聚合获取某段时间内的平均响应时间、最常访问页面路径或者是最高收入的商品类别等等。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值