Elasticsearch 聚合分析(Aggregations)详解

Elasticsearch 聚合分析(Aggregations) 是其最强大的功能之一,远超传统数据库的 GROUP BY。它支持多维分析、嵌套聚合、管道聚合、统计计算等,广泛应用于数据分析、报表生成、搜索结果筛选(Facets)、监控系统等场景。

本文将全面详解 Aggregations 的类型、语法、使用场景与最佳实践。


一、什么是聚合(Aggregations)?

聚合(Aggregations) 是对搜索结果集进行 分组、统计、分析 的操作,返回结构化分析结果,而非原始文档。

✅ 类比 SQL:

SELECT category, COUNT(*), AVG(price) 
FROM products 
GROUP BY category 
HAVING COUNT(*) > 10;

在 Elasticsearch 中通过 aggs 实现。


二、聚合的基本结构

GET /index/_search
{
  "query": { ... },  // 先过滤数据
  "aggs": {
    "NAME": {        // 聚合名称(自定义)
      "AGG_TYPE": {  // 聚合类型(如 terms, avg)
        ...         // 聚合参数
      }
    }
  }
}
  • 聚合基于 查询结果集 执行;
  • 可嵌套、可组合;
  • 不影响 _source 返回的文档。

三、四大类聚合详解

Elasticsearch 聚合分为四类:

类型说明示例
Metrics Aggregations计算数值指标(如平均值、总和)avg, sum, stats
Bucket Aggregations分组(如按品牌、价格段分组)terms, range, date_histogram
Pipeline Aggregations对其他聚合结果再计算derivative, moving_avg
Matrix Aggregations跨字段矩阵分析(实验性)matrix_stats

四、Metrics 聚合(指标聚合)

计算数值字段的统计信息。

1. avg / sum / min / max / value_count

"aggs": {
  "avg_price": { "avg": { "field": "price" } },
  "total_sales": { "sum": { "field": "sales_count" } },
  "min_price": { "min": { "field": "price" } },
  "doc_count": { "value_count": { "field": "title" } }
}

2. stats —— 一次性返回多个统计值

"aggs": {
  "price_stats": {
    "stats": { "field": "price" }
  }
}

返回:

{
  "count": 100,
  "min": 100.0,
  "max": 999.0,
  "avg": 450.0,
  "sum": 45000.0
}

3. extended_stats —— 扩展统计

包含方差、标准差等:

"aggs": {
  "price_extended": {
    "extended_stats": { "field": "price" }
  }
}

返回 std_deviation, variance, sum_of_squares 等。


4. percentiles —— 百分位数

用于分析延迟、响应时间分布:

"aggs": {
  "load_time_percentiles": {
    "percentiles": {
      "field": "load_time_ms",
      "percents": [50, 95, 99, 99.9]
    }
  }
}

返回 P50、P95、P99 等。


5. cardinality —— 去重计数(HyperLogLog)

估算唯一值数量,性能高:

"aggs": {
  "unique_users": {
    "cardinality": { "field": "user_id" }
  }
}

用于 UV 统计,误差率约 5%。


五、Bucket 聚合(桶聚合)

将文档分组到“桶”(Bucket)中,每个桶代表一组文档。

1. terms —— 按字段值分组(最常用)

"aggs": {
  "by_brand": {
    "terms": {
      "field": "brand",
      "size": 10,
      "order": { "_count": "desc" }
    }
  }
}
  • 适用于 keywordiplong 等字段;
  • size 控制返回桶数量;
  • 默认按文档数排序。

⚠️ 不适用于 text 字段(需开启 fielddata,不推荐)。


2. range —— 范围分组

"aggs": {
  "price_ranges": {
    "range": {
      "field": "price",
      "ranges": [
        { "to": 100000 },      // < 1000元
        { "from": 100000, "to": 500000 },
        { "from": 500000 }
      ]
    }
  }
}

3. date_histogram —— 时间直方图(最常用)

按时间间隔(如每小时、每天)分组。

"aggs": {
  "sales_per_day": {
    "date_histogram": {
      "field": "created_at",
      "calendar_interval": "day",
      "time_zone": "Asia/Shanghai"
    },
    "aggs": {
      "daily_revenue": { "sum": { "field": "price" } }
    }
  }
}
  • calendar_interval: second, minute, hour, day, week, month, quarter, year
  • 支持嵌套聚合(如每日销售额)

4. histogram —— 数值直方图

按固定间隔对数值分组:

"aggs": {
  "price_histogram": {
    "histogram": {
      "field": "price",
      "interval": 100000  // 每 1000 元一个桶
    }
  }
}

5. filters —— 自定义条件分组

"aggs": {
  "category_stats": {
    "filters": {
      "filters": {
        "electronics": { "term": { "category": "electronics" } },
        "clothing": { "term": { "category": "clothing" } },
        "high_price": { "range": { "price": { "gte": 500000 } } }
      }
    }
  }
}

6. significant_terms —— 显著项分析

找出与整体分布相比“显著不同”的项,用于异常检测。

"aggs": {
  "significant_brands": {
    "significant_terms": {
      "field": "brand"
    }
  }
}

示例:在“手机”类目中,“Apple” 出现频率远高于其他类目。


六、嵌套聚合(Nested Aggregations)

聚合可以嵌套,实现多维分析。

示例:按品牌分组,再统计价格分布

"aggs": {
  "by_brand": {
    "terms": { "field": "brand" },
    "aggs": {
      "price_stats": { "stats": { "field": "price" } },
      "price_ranges": {
        "range": {
          "field": "price",
          "ranges": [
            { "to": 500000 },
            { "from": 500000 }
          ]
        }
      }
    }
  }
}

返回:

"buckets": [
  {
    "key": "Apple",
    "doc_count": 15,
    "price_stats": { "avg": 899900, ... },
    "price_ranges": { "buckets": [...] }
  }
]

七、Pipeline 聚合(管道聚合)

对其他聚合的结果进行二次计算。

1. derivative —— 导数(变化量)

"aggs": {
  "sales_per_day": {
    "date_histogram": { "field": "created_at", "calendar_interval": "day" },
    "aggs": {
      "daily_revenue": { "sum": { "field": "price" } },
      "revenue_change": { "derivative": { "buckets_path": "daily_revenue" } }
    }
  }
}

返回每天相比前一天的收入变化。


2. moving_avg —— 移动平均

"revenue_ma": {
  "moving_avg": {
    "buckets_path": "daily_revenue",
    "window": 7,
    "model": "holt_winters"
  }
}

用于趋势平滑。


3. bucket_script —— 自定义脚本计算

"profit_rate": {
  "bucket_script": {
    "buckets_path": {
      "revenue": "daily_revenue",
      "cost": "daily_cost"
    },
    "script": "params.revenue > 0 ? (params.revenue - params.cost) / params.revenue : 0"
  }
}

八、聚合性能优化建议 ✅

场景建议
terms 聚合使用 keyword 字段,避免 text
大基数字段启用 execution_hint: "map""global_ordinals"
深度嵌套避免过深,影响性能
cardinality接受一定误差,性能远高于 terms + size=10000
date_histogram使用 fixed_interval 而非 calendar_interval(更高效)
分页聚合使用 composite 聚合支持深度分页

九、Composite Aggregation(复合聚合)

用于深度分页和大规模聚合。

"aggs": {
  "my_buckets": {
    "composite": {
      "sources": [
        { "brand": { "terms": { "field": "brand" } } },
        { "category": { "terms": { "field": "category" } } }
      ],
      "size": 10
    }
  }
}

支持 after 分页:

"after": { "brand": "Xiaomi", "category": "phone" }

✅ 替代 terms + size=10000 的深度分页方案。


十、完整示例:电商数据分析

GET /sales/_search
{
  "size": 0,
  "query": {
    "range": {
      "created_at": {
        "gte": "2024-01-01",
        "lt": "2024-07-01"
      }
    }
  },
  "aggs": {
    "monthly_sales": {
      "date_histogram": {
        "field": "created_at",
        "calendar_interval": "month"
      },
      "aggs": {
        "revenue": { "sum": { "field": "price" } },
        "avg_order_value": { "avg": { "field": "price" } },
        "top_brands": {
          "terms": { "field": "brand", "size": 5 },
          "aggs": {
            "category_breakdown": {
              "terms": { "field": "category" }
            }
          }
        }
      }
    },
    "overall_stats": {
      "stats": { "field": "price" }
    }
  }
}

十一、总结:聚合类型速查表

聚合类型用途是否支持嵌套
terms按字段分组
date_histogram时间序列分析
range范围分组
avg / sum数值统计
cardinality去重计数
percentiles分位数分析
significant_terms异常项检测
derivative变化量
bucket_script自定义计算
composite深度分页
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值