Elasticsearch : 正确认识使用Date类型

828 阅读4分钟

引用文档: elasticsearch date

简述

在 Elasticsearch 中,date 类型使用了一个可读的日期字符串或其它日期格式进行存储。在内部,Elasticsearch 使用了UTC时间的 long 型表示形式来存储日期,单位是毫秒(自1970年1月1日以来的毫秒数)。
在没有定义默认值时使用 strict_date_optional_time||epoch_millis 作为 date 类型的默认值。

strict_date_optional_time 类型为ISO日期格式,包含yyyy-MM-dd'T'HH:mm:ss.SSSZ or yyyy-MM-dd

注:Elasticsearch是基于Java开发的,并且在处理日期和时间时,采用了与Java的SimpleDateFormat类似的格式化模式。同时,Data类型支持带小数点的数值输入,但是会丢失精度,要避免这种输入。

Elasticsearch 中有关于时间的类型有两种 DateDate nanoseconds 两种。其中 Date nanoseconds在ES7.0.0大版本更新中被正式引入,用来满足更高精度的时间需求。

在 Elasticsearch 7.0 之前,只能以毫秒精度存储时间戳。如果要处理发生在更高频率的事件,例如存储和分析 Elasticsearch 中的跟踪或网络数据包数据,可能需要更高的精度。过去,我们使用 Joda 时间库来处理日期和时间,而 Joda 缺乏对高精度时间戳的支持。 随着 JDK 8 的推出,引入了官方的 Java 时间 API,它也可以处理纳秒精度的时间戳。过去的一年中,我们一直在努力将我们对 Joda 时间的使用迁移到原生的 Java 时间,并尽力保持向后兼容性。从 7.0.0 版本开始,您现在可以通过专用的 date_nanos 字段映射器使用这些纳秒级时间戳。需要注意的是,此字段的聚合仍然以毫秒的分辨率进行,以避免出现大量的 bucket。 —— 机翻介绍

可以将多个格式字符串组合在一起,使用||作为分隔符,这样就可以同时支持多种不同的日期格式。


常用的时间格式

Epoch,时期; 纪元;世;新时代;指的是一个特定的时间:1970-01-01 00:00:00 UTC
strict,表示对日期时间的格式启用了严格的检查,日期缺少前缀0的情况将不被接受,例如: 11/1 的写法是不被接受的,应该纠正为 11/01

  • epoch_millisepoch起的毫秒级时间戳。受到JAVA中Long类型长度的限制,最小最大值范围为 Long.MIN_VALUE and Long.MAX_VALUE
  • epoch_secondepoch起的秒级时间戳。
  • date_optional_time or strict_date_optional_time ISO日期格式,包含yyyy-MM-dd'T'HH:mm:ss.SSSZ or yyyy-MM-dd

官方详细文档


用法注意

PUT my-index-000002
{
  "mappings": {
    "properties": {
      "date": {
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
      }
    }
  }
}

PUT my-index-000002/_doc/2
{ "date": "2015-01-01" }

PUT my-index-000002/_doc/3
{ "date": "2024-01-09 19:19:53" }

PUT my-index-000002/_doc/4
{ "date": 1704799193000 }

GET my-index-000002/_search
{
  "sort": { "date": "asc"} 
}

GET my-index-000002/_search
{
  "query" : {
    "range": {
      "date": {
        "gte": "2024-01-09 19:19:53"
      }
    }
  }
}
  • 以上创建了格式为"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"date类型,并插入了3条数据。特别要注意的是,在插入混合格式的日期时间数据时,要注意时区的问题。在东8区,文档3 2024-01-09 19:19:53 和 文档4 1704799193000 可以认为是同一个时间。Elasticsearch 中的时间是从 1970-01-01 00:00:00 UTC 开始计算,当2024-01-09 19:19:53 存储时,其转换自然和 1704799193000 不是同一个时间。通过GET可以看到实际存储的时间为 1704827993000,差值 28800000 毫秒。在搜索的时候,可能不知觉地出现一些问题。
{
  "took": 0,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 3,
      "relation": "eq"
    },
    "max_score": null,
    "hits": [
      {
        "_index": "my-index-000002",
        "_id": "2",
        "_score": null,
        "_source": {
          "date": "2015-01-01"
        },
        "sort": [
          1420070400000
        ]
      },
      {
        "_index": "my-index-000002",
        "_id": "4",
        "_score": null,
        "_source": {
          "date": 1704799193000
        },
        "sort": [
          1704799193000
        ]
      },
      {
        "_index": "my-index-000002",
        "_id": "3",
        "_score": null,
        "_source": {
          "date": "2024-01-09 19:19:53"
        },
        "sort": [
          1704827993000
        ]
      }
    ]
  }
}