1. Elasticsearch 如何定制聚合结果的显示方式?

核心比喻:像“超市货架整理师”一样分类和统计商品
  • 问题
    你想知道“每周的订单量”,但默认的聚合结果可能返回时间戳和数值,比如 {"key": 1700000000, "doc_count": 15},难以直接阅读。
  • 解决办法
    使用 聚合格式化参数,像“超市货架标签”一样,将时间戳转为“2023-10-01”或“第40周”,并控制显示的字段。

2. 定制聚合结果的组成部分

核心组成部分
  1. 聚合类型
    • 日期直方图(date_histogram):按周、日、小时统计。
    • 术语聚合(terms):按分类、状态统计。
  2. 格式化参数
    • format:将时间戳转为可读格式(如 yyyy-MM-dd)。
    • calendar_interval:按周、月等自然时间间隔聚合。
  3. 扩展统计(Metrics)
    • 计算总销售额、平均价格等。
  4. 别名(Meta):给聚合结果添加描述性名称。

3. 使用场景

  • 电商分析
    统计“每周的订单量”或“每月的销售额”。
  • 日志监控
    统计“每天的错误日志数量”或“每小时的请求次数”。
  • 用户活跃度
    统计“每周新用户注册量”或“每日活跃用户数”。

4. 底层原理

(1) 聚合处理流程
  1. 数据分组
    • 根据聚合类型(如周)将数据分组(如 2023-10-012023-10-07 的订单)。
  2. 计算统计值
    • 每个组统计文档数(doc_count)、总销售额等。
  3. 格式化结果
    • 将时间戳转换为可读格式(如 2023-Week 40)。
    • 添加别名或扩展统计字段。
(2) 核心机制
  • 日期直方图(date_histogram)
    将时间字段按间隔(如周)分桶,统计每桶的文档数。
  • 格式化参数
    使用 format 将时间戳转为 yyyy-MM-ddyyyy-ww(年-周)。
  • 元数据(Meta)
    添加自定义标签,方便结果解读。

5. 流程图

以下是聚合结果定制的流程:

+-------------------+
| 用户发送聚合查询  |  (如统计每周订单量)
+-------------------+
         |
         v
+-------------------+
| Elasticsearch     |
| 处理聚合          |
| 1. 按周分组       |
| 2. 统计每组订单数 |
| 3. 格式化时间     |
| 4. 添加元数据     |
+-------------------+
         |
         v
+-------------------+
| 返回格式化结果    |  (如 "2023-Week 40": 150单)
+-------------------+

6. 概念图

以下是聚合定制的核心概念:

+-------------------+
| 聚合格式化        |
+-------------------+
         |
         v
+-------------------+
| 聚合类型          |  (如 date_histogram)
+-------------------+
         |
         v
+-------------------+
| 格式化参数        |  (如 format: "yyyy-ww")
+-------------------+
         |
         v
+-------------------+
| 扩展统计          |  (如总销售额)
+-------------------+
         |
         v
+-------------------+
| 元数据(Meta)    |  (如 "name": "每周订单统计")
+-------------------+

7. UML 类图

以下是简化后的 UML 类图:

+-------------------+
| Aggregation       |
+-------------------+
| - type: string    |  (如 "date_histogram")
| - field: string   |  (如 "order_date")
| - format: string  |  (如 "yyyy-ww")
| - meta: object    |  (自定义元数据)
+-------------------+

+-------------------+
| HistogramResult   |
+-------------------+
| - buckets: array  |  (每个时间段的统计结果)
| - doc_count: int  |  (每组文档数量)
| - meta: object    |  (自定义标签)
+-------------------+

8. 思维导图

以下是聚合定制的思维导图:

+-------------------+
| 聚合结果定制      |
+-------------------+
| + 核心步骤        |
|   + 选择聚合类型  |
|   + 设置格式      |
|   + 添加统计      |
|   + 自定义元数据  |
| + 参数设置        |
|   + 时间间隔      |
|   + 格式化        |
|   + 统计类型      |
| + 输出控制        |
|   + 可读时间      |
|   + 自定义标签    |
+-------------------+

9. 实例代码(PHP 演示聚合格式化)

以下是 PHP 代码示例,演示如何按周统计订单量并格式化结果:

<?php

// 1. 安装 Elasticsearch 客户端库(需要先执行:composer require elasticsearch)
require 'vendor/autoload.php';

// 2. 创建客户端连接到服务器
use Elasticsearch\ClientBuilder;

$client = ClientBuilder::create()
    ->setHosts(['http://localhost:9200'])
    ->build();

// 3. 创建索引并定义字段
$params = [
    'index' => 'order_index',
    'body' => [
        'mappings' => [
            'properties' => [
                'order_date' => ['type' => 'date'],
                'price' => ['type' => 'integer']
            ]
        ]
    ]
];
$client->indices()->create($params);

// 4. 插入测试数据(假设订单在2023年10月第一周)
for ($i = 1; $i <= 10; $i++) {
    $client->index([
        'index' => 'order_index',
        'id' => $i,
        'body' => [
            'order_date' => '2023-10-0' . $i, // 10月1日到10月10日
            'price' => 99
        ]
    ]);
}

// 5. 聚合查询:统计每周订单量并格式化为 "年-周" 格式
$searchParams = [
    'index' => 'order_index',
    'body' => [
        'size' => 0, // 不返回文档,只返回聚合
        'aggs' => [
            'weekly_orders' => [
                'date_histogram' => [
                    'field' => 'order_date', // 聚合的字段
                    'calendar_interval' => 'week', // 按周统计
                    'format' => 'yyyy-ww', // 格式化为 "年-周"
                    'time_zone' => '+08:00' // 时区设置
                ],
                'aggs' => [
                    'total_sales' => [
                        'sum' => [
                            'field' => 'price' // 统计总销售额
                        ]
                    ]
                ]
            ],
            'meta_info' => [
                'meta' => [
                    'name' => '每周订单统计' // 自定义标签
                ]
            ]
        ]
    ]
];

// 6. 执行查询
$searchResult = $client->search($searchParams);
print_r($searchResult); // 输出每周的订单量和销售额

// 7. 清理
$client->indices()->delete(['index' => 'order_index']);

代码注释详细解释

第 5 步:日期直方图聚合
'date_histogram' => [
    'field' => 'order_date',
    'calendar_interval' => 'week',
    'format' => 'yyyy-ww',
    'time_zone' => '+08:00'
]
  1. 作用:按周分组订单,并将时间格式化为 年-周(如 2023-40)。
  2. 为什么这么写:需要统计每周订单量,且希望结果更易读。
  3. 知识点date_histogram 聚合和 calendar_interval 参数。
第 5 步:扩展统计(总销售额)
'total_sales' => [
    'sum' => ['field' => 'price']
]
  1. 作用:在每组中计算总销售额。
  2. 为什么这么写:除了订单量,还需知道每周的销售额。
  3. 知识点:嵌套聚合(在日期直方图中嵌套 sum 聚合)。
第 5 步:元数据(Meta)
'meta_info' => [
    'meta' => ['name' => '每周订单统计']
]
  1. 作用:添加自定义标签,方便结果解读。
  2. 为什么这么写:让结果更具描述性,避免混淆。
  3. 知识点meta 参数用于添加元数据。
查询结果示例
{
  "aggregations": {
    "weekly_orders": {
      "buckets": [
        {
          "key_as_string": "2023-40", // 格式化后的时间(2023年第40周)
          "key": 1696118400, // UTC 时间戳
          "doc_count": 10, // 本周订单量
          "total_sales": {"value": 990} // 总销售额
        }
      ],
      "meta": {"name": "每周订单统计"}
    }
  }
}

10. 详细说明

(1) 聚合类型选择
  • date_histogram:按时间间隔(周、日)分组。
  • terms:按分类(如商品类型)分组。
  • stats/sum:计算总和、平均值等。
(2) 格式化参数
  • format
    • yyyy-ww:年-周(如 2023-40)。
    • yyyy-MM-dd:年-月-日。
  • calendar_interval
    • week:按自然周分组。
    • month:按月分组。
(3) 元数据(Meta)
  • 作用:添加描述性标签,方便结果解读。
  • 示例
    "meta": {"description": "按 UTC+8 时区统计"}
    

11. 总结

  • 聚合结果定制像“超市货架整理”
    • 分组:按周、月、分类分组。
    • 统计:计算订单量、销售额等。
    • 格式化:将时间戳转为可读格式,添加标签。
  • 核心功能
    灵活统计数据、生成可读性强的报表。
  • 底层原理
    Elasticsearch 根据聚合类型分组数据,通过 formatmeta 参数控制显示格式。
Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐