📣 极限科技诚招搜索运维工程师(Elasticsearch/Easysearch)- 全职/北京 👉 : 立即申请加入

在数据统计和可视化场景中,排行榜和趋势图是最常见的图表类型,它们分别用于展示分类排行和时间序列变化。Easysearch 的聚合功能,特别是 date_histogram,能够帮助我们通过一次查询就计算出这些统计结果,并用很少的数据处理工作就绘制出图表。

本文带你从原理到实践逐步掌握如何使用 Easysearch 的 date_histogram 聚合做排行榜和趋势图。


一、Easysearch 简要介绍 #

Easysearch 是一款分布式搜索与分析引擎,在支持全文检索能力的基础上,还提供了强大的聚合分析能力,可以对匹配的数据进行统计性的提取。你可以利用聚合完成各种统计分析的任务,而不需要额外的数据库或中间计算层。

聚合分析通常用于构建:

  • 趋势图(时间序列展示)
  • 排行榜(分类排名)
  • 报表统计
  • 实时监控指标

二、date_histogram 聚合:时间统计的核心能力 #

在 Easysearch 中,date_histogram 是最常用、也是最容易产生价值的一类聚合。
它的作用只有一件事:

按照时间维度,把数据切成连续的时间段,并在每个时间段内做统计。

只要你的数据中存在时间字段(如日志时间、下单时间、事件发生时间),date_histogram 几乎都是构建趋势图、排行榜和监控看板的首选工具。


2.1 date_histogram 是如何工作的 #

从行为上看,date_histogram 的工作方式可以理解为三步:

  1. 读取每条数据的时间字段
  2. 按指定规则,将时间划分成一个个“时间桶”
  3. 每个时间桶内,统计文档数量或子聚合结果

最终返回的不是单条数据,而是一组按时间顺序排列的统计结果,非常适合直接用于图表展示。


2.2 两种时间切分方式:calendar_intervalfixed_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 一次查询就能搞定。