目 录CONTENT

文章目录

【入门篇】8.Elasticsearch查询之Date Range聚合

冰点
2023-06-20 / 0 评论 / 0 点赞 / 28 阅读 / 8048 字

官网文档,里面的例子太多了,我就一些典型的我们来试试。

https://www.elastic.co/guide/en/elasticsearch/reference/8.18/search-aggregations-bucket-daterange-aggregation.html

场景:你是电商运营,想知道去年双11到双12期间的订单量,或者近三个月哪个月份销售额最高。这时候,Elasticsearch的Date Range聚合就像个时间管理大师,能把数据按你指定的时间段「咔咔」分组,比翻日历算日子可快多了!

啥是Date Range聚合?先看个栗子

简单说,它就是按时间范围把数据「装到不同的盒子里」。比如你想统计:

  • 今年1月1日到3月31日的订单

  • 4月1日到6月30日的订单

  • 7月1日以后的订单

只需要定义几个时间范围,Date Range聚合会自动把每个文档按日期字段归类到对应的盒子里。而且它比普通的range聚合更智能,支持日期数学表达式(比如now-1d代表昨天),还能指定日期格式,简直是时间数据的「分拣神器」。

实战:用Date Range分析电商订单

先整个订单索引,包含订单日期和金额字段:

PUT /order_data
{
  "mappings": {
    "properties": {
      "order_date": { "type": "date" },
      "amount": { "type": "double" }
    }
  }
}

塞点测试数据,模拟不同时间段的订单:

POST /order_data/_bulk
{"index":{"_id":1}}
{"order_date":"2024-11-11T00:00:00Z", "amount":1299}
{"index":{"_id":2}}
{"order_date":"2024-11-30T00:00:00Z", "amount":899}
{"index":{"_id":3}}
{"order_date":"2024-12-12T00:00:00Z", "amount":1599}
{"index":{"_id":4}}
{"order_date":"2025-01-01T00:00:00Z", "amount":999}
{"index":{"_id":5}}
{"order_date":"2025-02-14T00:00:00Z", "amount":1399}

现在想按季度分组,看看每个季度的订单金额总和,咋整?用Date Range聚合:

GET /order_data/_search
{
  "size": 0,
  "aggs": {
    "quarterly_sales": {
      "date_range": {
        "field": "order_date",
        "format": "yyyy-MM",
        "ranges": [
          { "from": "2024-11-01", "to": "2024-12-31" },
          { "from": "2025-01-01", "to": "2025-03-31" }
        ]
      },
      "aggs": {
        "total_amount": {
          "sum": { "field": "amount" }
        }
      }
    }
  }
}

这里field指定日期字段,format定义返回的日期格式,ranges里写具体时间段。每个时间段对应一个桶,然后在每个桶里用sum聚合算金额总和。

执行结果:时间分段数据一目了然

{
  "aggregations": {
    "quarterly_sales": {
      "buckets": [
        {
          "key": "2024-11-01 to 2024-12-31",
          "from": 1730332800000,
          "to": 1732924800000,
          "doc_count": 3,
          "total_amount": {
            "value": 3797
          }
        },
        {
          "key": "2025-01-01 to 2025-03-31",
          "from": 1732924800000,
          "to": 1735603200000,
          "doc_count": 2,
          "total_amount": {
            "value": 2398
          }
        }
      ]
    }
  }
}

结果里每个桶显示:

  • key:时间段描述

  • doc_count:该时间段的订单数量

  • total_amount:该时间段的订单总金额

一眼就能看出2024年11-12月卖了3797元,2025年1-3月卖了2398元,哪个时间段卖得好清清楚楚!

进阶玩法:用日期数学表达式偷懒

有时候不想写死具体日期,比如想查「昨天」「上周」「本月」的数据,Date Range支持超方便的日期数学表达式:

GET /order_data/_search
{
  "size": 0,
  "aggs": {
    "recent_sales": {
      "date_range": {
        "field": "order_date",
        "format": "yyyy-MM-dd",
        "ranges": [
          { "to": "now-1d" },        // 昨天及以前
          { "from": "now-7d", "to": "now-1d" },  // 上周(7天前到昨天)
          { "from": "now-30d" }       // 近30天
        ]
      }
    }
  }
}

now代表当前时间,now-1d就是「当前时间减1天」,now-7d是「当前时间减7天」,是不是比算具体日期省事多了?

注意事项:别踩时间格式的坑

  1. 日期字段类型必须正确:确保字段映射为date类型,不然聚合会报错。

  2. from和to的包含关系:Date Range默认包含from,不包含to,比如from:2024-11-01 to:2024-12-31会包含11月1日,不包含12月31日23:59:59之后的数据。

  3. 时区问题:Elasticsearch默认用UTC时区,如果你存的是本地时间,可能需要用time_zone参数调整,比如time_zone: "+08:00"设置为北京时间。

0

评论区