深入 Kibana 06 - 聚合式可视化的老路:Visualize 与 bucket/metric
上一篇展示了 Discover 的执行模型——三类并发请求共享一个父 Search Source,文档检索与直方图各自用子 Search Source 覆盖差异。这一篇进入聚合式可视化。聚合式可视化容易被误解成"拖几个字段选一种图表类型"。更准确的说法是:Visualize 里的每一张图都是对 Elasticsearch 聚合 API 的一次声明——图表类型只是渲染方式,图形背后的数据来自一棵 ES aggregation tree;bucket 聚合决定 X 轴的分组方式,metric 聚合决定 Y 轴的数值,嵌套 bucket 就是树的多层分叉。本文只抓一个问题:bucket 嵌套如何映射到 ES 的 aggregation 树结构,以及 Visualize 作为这条旧路的设计模型——因为理解它,才能理解 Lens 为什么要重新设计。
每张图 = 一次聚合查询
Visualize 编辑器里,用户通过"Buckets"和"Metrics"两组配置描述一张图。这组配置直接对应 ES 的 aggregations 请求体:
1 | |
聚合树的深度等于 bucket 嵌套层数加一(metric 层)。Visualize 的"Split series"就是在当前 bucket 下再嵌一层 terms bucket;"Split chart"是在最外层再嵌一层 bucket,生成多张并排小图。
Bucket 聚合 vs Metric 聚合
ES 的聚合分两大类,Visualize 把这两类直接暴露给用户。
Bucket 聚合(分组器)——把文档集合切分成桶,每个桶是一个子文档集合:
1 | |
Metric 聚合(度量器)——对一个桶内的文档集合计算一个数值:
1 | |
Pipeline 聚合(后处理器)——在已有聚合结果上做二次计算:
1 | |
Visualize 的 TSVB(Time Series Visual Builder)和 Vega 可视化能使用更复杂的 pipeline 聚合;标准 Visualize 编辑器只暴露了最常用的子集。
Aggregation Tree 的映射规则
Visualize 把用户配置翻译成 aggregation tree 时遵循一套固定规则:
1 | |
这意味着:Buckets 配置里的顺序决定了 ES 里的嵌套顺序,改变顺序会产生不同的聚合树,返回的数据结构也不同,即使 metric 结果"数值上相同",行列关系会变。
一个直接推论:"Split chart"和"Split series"的本质差异是 bucket 在树里的深度不同。Split chart 把变量放在外层,导致每个外层桶渲染成独立小图;Split series 把变量放在内层,导致同一个外层桶里的不同 term 渲染成同一张图里的多条线。
图表类型是渲染层
Visualize 支持的图表类型(Bar/Line/Area/Pie/Data Table 等)是对同一份聚合结果的不同渲染方式,不影响发往 ES 的聚合请求:
1 | |
这个"聚合与渲染分离"的设计意味着切换图表类型不需要重新发 ES 请求(已缓存的聚合结果直接复用),但也意味着某些图表类型对 bucket 层数有隐含约束(Pie 只展示一层 bucket,强行加多层会只显示最内层)。
Lens(Kibana 7.5 起逐步替代 Visualize 的编辑器)打破了这个绑定:Lens 允许用户先选择"维度"和"度量",编辑器自动推断合适的图表类型和聚合结构,而不是要求用户手动配置 bucket/metric 的嵌套顺序。Visualize 的这条旧路依然存在,但新建图表推荐用 Lens。
Visualize 的 Saved Object 结构
保存一张 Visualize 图,写入一个 type: visualization 的 Saved Object,关键的 attributes 字段是 visState(JSON 字符串):
1 | |
schema 字段把每个 agg 映射到图表里的角色:segment = X 轴 bucket,group = Split series bucket,split = Split chart bucket,metric = Y 轴度量。ES 请求的嵌套顺序由 schema 决定,而不是 aggs 数组顺序。
这个 Saved Object 的 references 里有一条指向所用 Data View 的引用,和 Saved Search 的结构一致。
实验:用 Inspect 捕获聚合 JSON
以下步骤在 Kibana 7.x / 8.x 的 Visualize 编辑器中可执行:
-
在 Visualize 里新建一张 Bar chart,选择一个包含数值字段的 Data View(例如日志 Data View,含
bytes和status字段)。 -
配置:
- Metrics → Y-axis → Aggregation: Average,Field: bytes
- Buckets → X-axis → Aggregation: Date Histogram,Field: @timestamp
- 点击 Add sub-buckets → Split series → Aggregation: Terms,Field: status,Size: 5
-
点击"Update"刷新图表,然后点击 Inspect 按钮,切换到"Requests"标签,展开请求体。
-
在请求体的
aggs段,验证:- 外层是
date_histogram,字段是@timestamp - 嵌套在
date_histogram内的是terms,字段是status - 嵌套在
terms内的是avg,字段是bytes - 请求
size: 0(不返回文档)
- 外层是
-
在 Buckets 配置面板里,将 Split series 上移到 X-axis 的上面(改变 bucket 顺序),再次 Update,观察聚合树是否外层变成了
terms、内层变成了date_histogram——验证顺序决定嵌套深度。 -
添加一条 Pipeline 聚合:Y-axis → Add metric → Aggregation: Moving Average,选择上面的 Average metric 作为源。再次检查请求体,找到
moving_avg(或moving_fn)出现在pipeline_aggs位置。
聚合嵌套示意(多层 bucket)
1 | |
渲染为 Split chart 时:status=200 和 status=500 各生成一张独立小图,每张图 X 轴为时间,Y 轴为 avg(bytes)。
模式提炼
1 | |
工程迁移表
| Visualize / ES 聚合概念 | 工程类比 |
|---|---|
| bucket agg (terms / date_histogram) | SQL GROUP BY field1, field2 |
| metric agg (avg / sum / cardinality) | SQL AVG() / SUM() / COUNT(DISTINCT) |
| 嵌套 bucket = aggregation tree | SQL 多级 GROUP BY / pivot 表 |
| pipeline agg (moving_avg, derivative) | SQL window function (AVG() OVER) |
| Split chart vs Split series | SQL GROUP BY 外层维度 vs 内层维度 |
| size: 0 | SQL SELECT ... GROUP BY(无 SELECT *) |
| visState aggs[] schema | Grafana panel query 的 group by / metric 配置 |
| Visualize Saved Object | Grafana Dashboard panel JSON |
| 电子表格 pivot 表 | 行/列/值 = bucket1/bucket2/metric |
常见误解
误解一:“切换图表类型会重新发请求”。切换图表类型(Bar → Line → Area)只改变渲染层,聚合请求结果被缓存复用,不触发新的 ES 请求。只有改变 Buckets / Metrics 配置并点击 Update 才会重新发请求。
误解二:“terms 聚合返回所有唯一值”。terms 聚合默认只返回 top N(默认 size: 10)个桶,按文档数降序排列;其余的归入 sum_other_doc_count。如果字段基数很高(如 user_id),调大 size 会显著增加 ES 内存开销。Visualize 里的 Terms bucket 配置里的"Size"选项直接对应这个参数。
误解三:“Visualize 已经被废弃,不需要了解它”。当前(自 Kibana 8.x 起)Visualize 仍然存在,旧版 Dashboard 里的 Visualize 类型面板仍然跑在 Visualize 引擎上。Lens 是推荐的新建方式,但大量存量图表仍是 Visualize 格式。更重要的是:Visualize 的 bucket/metric 模型和 aggregation tree 的对应关系,是理解 Lens 为什么要引入"维度"抽象、为什么能自动推断图表类型的前置知识。
误解四:“cardinality 聚合是精确去重”。cardinality 使用 HyperLogLog++ 算法,是近似值,默认精度参数 precision_threshold: 3000,误差率约 5%。在基数大于 precision_threshold 时,结果是估算。需要精确去重计数时,只能对文档先做 filter 再 count,或用 composite 聚合逐页枚举。
练习
-
在 Visualize 里建一张 Data Table,Buckets 加两层:外层
termson status(size:3),内层date_histogramon @timestamp(interval: 1d);Metrics 加sumof bytes 和cardinalityof session_id(如有该字段)。用 Inspect 确认 aggregation tree 的嵌套结构,然后在 ES Dev Tools 里手动重现同一个请求,对比两者的 JSON。 -
交换两个 bucket 的顺序(外层改为 date_histogram,内层改为 terms),观察 Inspect 里聚合树的变化,以及 Data Table 里行列分组的变化——验证顺序 = 树深度 = 分组语义。
-
思考题:Grafana 的 panel 查询模型(group by 时间 + 聚合函数)和 Visualize 的 bucket/metric 模型有什么结构上的同构?两者都能做"按时间分桶 + 按字段拆系列 + 指定 metric",但 Grafana 支持多种数据源,Visualize 深度绑定 ES。这个差异在工程上意味着什么取舍?(提示:第 16 篇会展开对比。)
系列导航
| 序号 | 主题 | 状态 |
|---|---|---|
| 00 | 导读:Kibana 的状态存在 Elasticsearch 里 | 已发布 |
| 01 | Kibana 架构:浏览器、Node.js server 与 New Platform | |
| 02 | Saved Object:Kibana 一切状态的统一模型 | |
| 03 | Data View(Index Pattern):查询之前的字段抽象 | |
| 04 | Search Source 与查询翻译:KQL、Lucene 与 Query DSL | |
| 05 | Discover:交互式检索的执行模型 | 上一篇 |
| 06 | 聚合式可视化的老路:Visualize 与 bucket/metric | 本篇 |
| 07 | Lens:字段拖拽与自动推断的新路 | 下一篇 |
| 08 | TSVB:时序可视化的专用编辑器 | |
| 09 | Dashboard:Embeddable 组合与容器协议 | |
| 10-12 | 告警、上报与自动化 | 后续阶段 |
| 13-15 | 平台、安全与扩展 | 后续阶段 |
| 16-17 | 演进、生态与对比 | 后续阶段 |
参考资料
- Kibana 官方文档 Visualize:https://www.elastic.co/guide/en/kibana/current/visualize.html
- ES Bucket aggregations:https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket.html
- ES Metric aggregations:https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics.html
- ES Pipeline aggregations:https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-pipeline.html
- ES terms aggregation(size 与精度):https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-terms-aggregation.html
- ES cardinality aggregation(HyperLogLog++):https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-cardinality-aggregation.html
- Kibana Lens 文档(Visualize 的继任者):https://www.elastic.co/guide/en/kibana/current/lens.html
