文章二十八:ElasticSearch 运用指标聚合快速统计数值

在海量业务数据场景中(如电商订单统计、日志数据分析、用户行为监控),快速完成求和、平均值、最大值、最小值、去重计数、百分位 等数值统计是核心需求。Elasticsearch(简称 ES)提供的指标聚合(Metrics Aggregations) 功能,无需复杂的 SQL 计算,就能对海量数据实现毫秒级数值统计,是大数据实时分析的核心能力。

本文将全面讲解 ES 指标聚合的核心概念、常用语法、实战场景与最佳实践,帮助你快速掌握 ES 数值统计的核心用法,适配生产环境的实时数据统计需求。

metric指标聚合

为了便于大家得理解和查看,为大家展示了一下我得示例得数据,大家可以直接copy一下:

复制代码
# 创建订单索引(设置字段类型,保证数值聚合正常执行)
PUT order_index
{
  "settings": {
    "number_of_replicas": 0
  }, 
  "mappings": {
    "properties": {
      "order_id": { "type": "keyword" },
      "price": { "type": "double" },  // 数值型,支持聚合计算
      "pay_num": { "type": "integer" },
      "order_time": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss" },
      "category": { "type": "keyword" }
    }
  }
}

# 批量插入测试数据
POST order_index/_bulk?refresh=true
{"index":{"_id":1}}
{"order_id":"ORDER_001","price":99.8,"pay_num":1,"order_time":"2025-01-01 10:00:00","category":"数码"}
{"index":{"_id":2}}
{"order_id":"ORDER_002","price":199.5,"pay_num":2,"order_time":"2025-01-01 11:00:00","category":"服饰"}
{"index":{"_id":3}}
{"order_id":"ORDER_003","price":299.0,"pay_num":1,"order_time":"2025-01-01 14:00:00","category":"数码"}
{"index":{"_id":4}}
{"order_id":"ORDER_004","price":88.6,"pay_num":1,"order_time":"2025-01-02 09:00:00","category":"食品"}

案例展示

复制代码
#获取价格中的stats
GET order_index/_search
{
  "_source":false, 
  "aggs": {
    "test_type": {
      "stats": {
        "field": "price"
      }
    }
  }
}

指标聚合函数

一、基础数值统计聚合(最常用)

核心:对数值字段做简单统计,你提到的 sum/max/min/avg 都在这一类

表格

聚合函数 中文名称 核心作用 适用场景
sum 求和聚合 计算字段所有值的总和 统计订单总金额、访问总次数、流量总量
max 最大值聚合 获取字段的最大值 查找最高温度、最大订单金额、最长响应时间
min 最小值聚合 获取字段的最小值 查找最低价格、最小库存、最短耗时
avg 平均值聚合 计算字段所有值的平均值 统计平均响应时间、平均客单价、平均评分
value_count 计数聚合 统计字段非空值的数量 统计有效数据条数、参与评分的用户数

二、高级数值统计聚合

核心:进阶统计,补充基础统计的不足,生产高频使用

表格

聚合函数 中文名称 核心作用 适用场景
stats 通用统计聚合 一次性返回 sum/max/min/avg/value_count 需要同时获取多个基础统计值时
extended_stats 扩展统计聚合 在 stats 基础上,增加方差、标准差、平方和等 数据分析、异常检测、数据分布统计
cardinality 基数聚合 统计字段去重后的值数量 统计独立 IP 数、独立用户数、独立商品数

三、百分位 / 分位数聚合(数据分析专用)

核心:用于数据分布、性能监控、阈值分析

聚合函数 中文名称 核心作用 适用场景
percentiles 百分位聚合 计算指定百分位的值(如 P50/P90/P99) 接口响应耗时分析(P99 耗时)、数据分布
percentile_ranks 百分位排名聚合 计算某个值在数据中的百分位排名 判断某个数值处于整体数据的什么水平

percentiles 案例讲解:

复制代码
GET page_study_index/_search
{
  "size":0,
  "aggs": {
    "agg_type_price": {
      "percentiles": {
        "field": "number",
        "percents": [
          0,
          1,
          5,
          25,
          50,
          75,
          95,
          99, 
          100
        ]
      }
    }
  }
}

结果演示:

复制代码
"aggregations" : {
  "agg_type_price" : {
    "values" : {
      "0.0" : 10,
      "1.0" : 15,
      "5.0" : 20,
      "25.0" : 50,
      "50.0" : 100,
      "75.0" : 150,
      "95.0" : 200,
      "99.0" : 220,
      "100.0": 250
    }
  }
}

这个结果可以这样理解:

  • "0.0" : 10 : 表示 number 字段的最小值是 10。
  • "50.0" : 100 : 表示有 50% 的数据,其 number 字段的值小于或等于 100。这也就是我们常说的中位数
  • "95.0" : 200 : 表示有 95% 的数据,其 number 字段的值小于或等于 200。
  • "100.0": 250 : 表示 number 字段的最大值是 250。

TDigest 的compression参数:

复制代码
GET page_study_index/_search
{
  "size":0,
  "aggs": {
    "agg_type_price": {
      "percentiles": {
        "field": "number",
        "percents": [
          50,
          75,
          95,
          99, 
          100
        ],
        "tdigest":{
          "compression":1000000
        }
      }
    }
  }
}

Digest 算法之所以能处理海量数据而不撑爆内存,是因为它不把每一个原始数据都存下来,而是把数据"压缩"成一个个小团体。

compression 参数直接决定了 TDigest 算法最多可以保留多少个"质心"

  • 公式(估算) :最大质心数量 ≈ 20 * compression
  • 直观理解
    • compression 值越大 ➔ 允许保留的质心越多 ➔ 数据压缩得越少 ➔ 精度越高 ,但内存占用越大
    • compression 值越小 ➔ 允许保留的质心越少 ➔ 数据被强行合并 ➔ 精度越低 ,但内存占用越小

四、地理指标聚合(地理数据专用)

核心:针对经纬度地理坐标字段

聚合函数 中文名称 核心作用 适用场景
geo_centroid 地理质心聚合 计算一组地理坐标的中心点 统计用户分布中心、门店覆盖中心
geo_bounds 地理边界聚合 计算坐标的最小 / 最大经纬度边界 绘制地理区域范围、地图展示边界

五、脚本 / 自定义值聚合

核心:基于脚本动态计算值,灵活适配复杂场景

聚合函数 中文名称 核心作用 适用场景
scripted_metric 脚本指标聚合 自定义脚本实现复杂聚合

直接在函数中使用脚本:

复制代码
GET page_study_index/_search
{
  "aggs": {
    "trest": {
      "avg": {
        "script": {
          "source": """ 
          //使用脚本将下面的number数据放大10倍
          doc['number'].value*10
          """
        }
      }
    }
  }
}

六、string_stats

是 Elasticsearch 中专门用于对字符串类型字段进行统计分析的聚合方式。

string_stats 是 Elasticsearch 中专门用于对字符串类型字段进行统计分析的聚合方式。

percentilesstats 等用于数值计算的聚合不同,string_stats 关注的是字符串本身的特征,比如长度和内容的多样性。

📊 它能提供哪些统计指标?

对一个字段使用 string_stats 后,你会得到以下几个核心指标:

  • count: 包含非空字符串的文档数量。
  • min_length: 所有字符串中的最短长度。
  • max_length: 所有字符串中的最长长度。
  • avg_length: 所有字符串的平均长度。
  • entropy: 信息熵。这是一个衡量字符串内容复杂度的指标,可以量化数据的多样性、相似性或随机性。熵值越高,说明字符串包含的字符种类越丰富,分布越均匀。

七:top_hits子聚合:

top_hits 和普通的查询不一样,它不是一个独立的聚合,而是一个指标聚合 。这意味着它必须依附于一个桶聚合 (比如 termsrange 等)才能工作。

这个在之后的桶聚合中还会讲解,但是因为他是属于指标聚合的,所以大家还是要理解他

下面的例子是,先使用桶聚合按着星期几进行分桶,之后返会每个桶中最相关的数据

复制代码
GET kibana_sample_data_ecommerce/_search
{
  "size":0,
  "aggs": {
    "test": {
      "terms": {
        "field": "day_of_week"
      },
      "aggs":{
        "top_Test":{
          "top_hits": {
            "size": 1
          }
        }
      }
    }
  }
}

指数聚合常见属性:

missing 参数 核心说明

参数 取值示例 含义
missing 数值 / 字符串 文档无该字段、字段为 null时,用设定的值替代,参与聚合计算;不设置则直接忽略该文档

使用参数效果展示:

没使用函数效果展示:

format临时解决数据精度问题:

在实际开发中我们可能只是需要在小数点之后保留两位小数,这是我们在进行数据统计的时候可以使用format进行一下格式化,保证保留两位小数。

复制代码
GET kibana_sample_data_ecommerce/_search
{
  "size":0,
  "_source":true, 
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "day_of_week": "Monday"
          }
        }
      ]
    }
  }, 
  "aggs": {
    "min_price_agg": {
      "stats": {
        "field": "products.min_price",
        "missing": 0,
         "format": "#.00"
      }
    }
  }
}

但是上面的方式只是解决这个问题的临时方案,最好的方案还是在创建mapping是指定的数据类型:

复制代码
"mappings": {
  "properties": {
    "products.min_price": {
      "type": "scaled_float",
      "scaling_factor": 100
    }
  }
}

实际上我们的数据是11.11,但是es会存成1111,这就解决了精度问题,但是我们在使用json进行展示的时候还是可能出现尾巴的问题,但是这个时候你加上 "format": "#.00"就可以解决问题了。

相关推荐
霸道流氓气质1 小时前
SpringBoot+LangChain4j+Ollama+MCP实现智能天气工具调用示例
java·spring boot·后端
sindyra1 小时前
享元模式(Flyweight Pattern)
java·开发语言·设计模式·享元模式·优缺点
这是程序猿1 小时前
设计模式入门:Java 单例模式(Singleton)详解,从入门到实战
java·单例模式·设计模式
codingPower1 小时前
ApplicationListener 和 SpringApplicationRunListener 深度解析对比
java·开发语言·spring boot
TENSORTEC腾视科技1 小时前
腾视科技重磅发布AD03行车记录仪DashCam!全维守护,智驭出行新生态
大数据·网络·人工智能·科技·ai·无人叉车解决方案·无人叉车及智能调度系统解决方案
森普智慧农业1 小时前
乡村振兴标杆之浙江安吉余村,智慧农业+生态振兴标杆
大数据·科技·生活
Volunteer Technology1 小时前
Hadoop之HDFS shell操作篇
大数据·hadoop·hdfs
ch.ju1 小时前
Java Programming Chapter 2-Recursion of function
java·开发语言
铁皮哥1 小时前
【后端开发】RabbitMQ、RocketMQ、Kafka 怎么选?我从业务场景重新梳理了一遍
java·linux·数据库·分布式·kafka·rabbitmq·rocketmq