在数据统计和可视化场景中,排行榜和趋势图是最常见的图表类型,它们分别用于展示分类排行和时间序列变化。Easysearch 的聚合功能,特别是 date_histogram,能够帮助我们通过一次查询就计算出这些统计结果,并用很少的数据处理工作就绘制出图表。
本文带你从原理到实践逐步掌握如何使用 Easysearch 的 date_histogram 聚合做排行榜和趋势图。
一、Easysearch 简要介绍 #
Easysearch 是一款分布式搜索与分析引擎,在支持全文检索能力的基础上,还提供了强大的聚合分析能力,可以对匹配的数据进行统计性的提取。你可以利用聚合完成各种统计分析的任务,而不需要额外的数据库或中间计算层。
聚合分析通常用于构建:
- 趋势图(时间序列展示)
- 排行榜(分类排名)
- 报表统计
- 实时监控指标
二、date_histogram 聚合:时间统计的核心能力
#
在 Easysearch 中,date_histogram 是最常用、也是最容易产生价值的一类聚合。
它的作用只有一件事:
按照时间维度,把数据切成连续的时间段,并在每个时间段内做统计。
只要你的数据中存在时间字段(如日志时间、下单时间、事件发生时间),date_histogram 几乎都是构建趋势图、排行榜和监控看板的首选工具。
2.1 date_histogram 是如何工作的
#
从行为上看,date_histogram 的工作方式可以理解为三步:
- 读取每条数据的时间字段
- 按指定规则,将时间划分成一个个“时间桶”
- 每个时间桶内,统计文档数量或子聚合结果
最终返回的不是单条数据,而是一组按时间顺序排列的统计结果,非常适合直接用于图表展示。
2.2 两种时间切分方式:calendar_interval 与 fixed_interval
#
在使用 date_histogram 时,最核心的选择其实只有一个:
时间是按照“日历概念”切,还是按照“固定时长”切?
Easysearch 提供了两种方式,分别对应两个参数。
2.2.1 calendar_interval:按自然日历切分
#
calendar_interval 使用的是日历语义,例如:
{
"date_histogram": {
"field": "@timestamp",
"calendar_interval": "day"
}
}
含义是:
- 一天,指的是自然日(00:00 ~ 24:00)
- 一周,指的是自然周
- 一个月,长度会随月份变化
这种方式更符合人的直觉,非常适合业务报表和运营分析。
常见使用场景包括:
- 每日 / 每周 / 每月趋势图
- 运营数据报表
- 按自然周期统计的排行榜
2.2.2 fixed_interval:按固定时间长度切分
#
fixed_interval 使用的是绝对时间长度,不关心日历含义:
{
"date_histogram": {
"field": "@timestamp",
"fixed_interval": "1h"
}
}
这表示:
- 每 1 小时切一个时间桶
- 无论是否跨天、跨月
- 每个时间桶长度始终一致
可以把它理解为:
“从某个时间点开始,每隔固定时间统计一次”
常见的 fixed_interval 值包括:
5m:每 5 分钟1h:每 1 小时30s:每 30 秒
2.2.3 两者的直观区别 #
用一句话概括区别:
**calendar_interval 关心“这是哪一天”
****fixed_interval 关心“过了多久时间”**
从实践角度看:
| 场景 | 推荐方式 |
|---|---|
| 业务趋势、日报、周报 | calendar_interval |
| 实时监控、指标统计 | fixed_interval |
| 滚动窗口分析 | fixed_interval |
| 运营分析 | calendar_interval |
2.3 一个容易被忽略但很重要的选择 #
在实际项目中,很多趋势图“看起来不对”,并不是数据问题,而是:
- 该用
calendar_interval的地方用了fixed_interval - 或者反过来
例如:
- 用
fixed_interval: 24h画“每日订单趋势” - 在跨时区或夏令时场景下,图表可能出现错位
因此,在写 date_histogram 之前,先明确业务语义,再选择参数,往往比调优更重要。
2.4 小结 #
date_histogram 看起来只是一个聚合参数,但它决定了:
- 时间如何被理解
- 趋势图是否可信
- 排行榜统计口径是否一致
记住一个简单原则即可:
**自然周期 → calendar_interval
****固定频率 → fixed_interval**
掌握这一点,date_histogram 的大部分使用问题,就已经解决了一半。
三、使用 date_histogram 做趋势图
#
趋势图通常用于展示某个指标随时间的变化,例如每天的访问量、每日订单数量等。
1. 场景:统计每日访问量趋势 #
假设我们有一个日志索引 logs,其中包含时间字段 @timestamp(UTC 格式),我们希望统计过去一段时间内每天访问次数。
① 聚合查询 #
GET logs/_search
{
"size": 0,
"aggs": {
"daily_visits": {
"date_histogram": {
"field": "@timestamp",
"calendar_interval": "day",
"format": "yyyy-MM-dd"
}
}
}
}
这条聚合表示:
- 按天进行分桶
- 每个桶表示某一天范围
- 每个桶返回该天的数据数量(文档数)
② 返回结果结构示例 #
{
"aggregations": {
"daily_visits": {
"buckets": [
{
"key_as_string": "2026-01-01",
"key": 1738252800000,
"doc_count": 1590
},
{
"key_as_string": "2026-01-02",
"key": 1738339200000,
"doc_count": 1842
},
{
"key_as_string": "2026-01-03",
"key": 1738339200000,
"doc_count": 2156
},
{
"key_as_string": "2026-01-04",
"key": 1738339200000,
"doc_count": 2367
}
]
}
}
}
说明:
key_as_string是时间段标签doc_count是该段内匹配的数据量
③ ECharts 折线图的可视化示例 #
如果使用 ECharts 可视化上述趋势图:
// 假设 response 即上面聚合结果
const buckets = response.aggregations.daily_visits.buckets;
// 1. 提取坐标数据
const xAxisData = buckets.map((b) => b.key_as_string);
const seriesData = buckets.map((b) => b.doc_count);
// 2. 配置 ECharts
const option = {
title: { text: "每日访问趋势" },
tooltip: { trigger: "axis" },
xAxis: {
type: "category",
data: xAxisData,
},
yAxis: { type: "value" },
series: [
{
name: "访问量",
type: "line",
data: seriesData,
smooth: true,
},
],
};
chart.setOption(option);

这个折线图可以直观地帮助你看到每天访问量的波动趋势。
四、用 date_histogram 做排行榜
#
你也可以结合分组聚合,在时间维度和其他字段上构建更复杂的排行榜。
1. 场景:每周热门产品排行 #
现在假设有订单索引 orders,其中包含:
order_time时间字段product_id产品字段
我们想统计过去一段时间内每周销量排行榜。
① 聚合查询结构 #
GET orders/_search
{
"size": 0,
"aggs": {
"weekly": {
"date_histogram": {
"field": "order_time",
"calendar_interval": "week",
"format": "yyyy-MM-dd"
},
"aggs": {
"top_products": {
"terms": {
"field": "product_id.keyword",
"size": 10
}
}
}
}
}
}
这条查询做了:
- 按周分桶
- 每周内部按产品分组并统计数量
② 返回结果结构示例(简化) #
{
"aggregations": {
"weekly": {
"buckets": [
{
"key_as_string": "2026-01-03",
"top_products": {
"buckets": [
{ "key": "P1", "doc_count": 140 },
{ "key": "P2", "doc_count": 98 },
{ "key": "P3", "doc_count": 226 }
]
}
}
]
}
}
}
每周的桶里,有一个大的 top_products 子聚合,用来展示产品排行榜。

③ 排行榜可视化实践 #
结合 ECharts,你可以为每个时间点生成一个排行榜视图,常见做法:
- 柱状图展示某个时间段内 Top N 排行
- 多维折线图(产品销量随时间变化趋势)
以下示例展示单周内的柱状图:
// 选取某一桶
const bucket = response.aggregations.weekly.buckets[0];
const productBuckets = bucket.top_products.buckets;
// ECharts 数据转换
const xAxisData = productBuckets.map((p) => p.key);
const seriesData = productBuckets.map((p) => p.doc_count);
const option = {
title: { text: `周销量排行榜(${bucket.key_as_string})` },
tooltip: {},
xAxis: {
type: "category",
data: xAxisData,
},
yAxis: { type: "value" },
series: [
{
name: "销量",
type: "bar",
data: seriesData,
},
],
};
chart.setOption(option);
五、更多进阶用法 #
1. 结合子聚合计算指标 #
你可以在 date_histogram 内进一步加入指标聚合,例如计算每段的总销售额:
"aggs": {
"daily_sales": {
"date_histogram": {
"field": "order_time",
"calendar_interval": "day",
"format": "yyyy-MM-dd"
},
"aggs": {
"total_amount": {
"sum": {
"field": "amount"
}
}
}
}
}
在每一天分桶内,会输出 total_amount.value 总销售额数据,可以在趋势图中画折线显示金额。
六、使用建议与注意事项 #
1. 合理选择时间粒度 #
粒度太细(如按分钟)可能会产生大量桶,影响性能;而粒度太粗则可能失去趋势细节。根据数据密度与展示需求调整 calendar_interval。
2. 时间格式输出 #
通过 format 参数可以设置时间字符串格式,便于图表展示。
3. 时区问题 #
默认情况下,时间按 UTC 存储并计算。如果要显示本地时间,需要在聚合中设置 time_zone 参数。
七、总结 #
通过 date_histogram 聚合,Easysearch 能够轻松实现:
- 趋势图(如每日/每周数据变化)
- 排行榜(时间分段内分组排行)
而且所有统计都可以通过一条请求完成。这不仅减少了后端计算与数据搬运工作,还能显著提升报表与看板的实时性。
一句话总结:排行榜 + 趋势图,用 Easysearch 一次查询就能搞定。





