• 【Elasticsearch教程11】Mapping字段类型之日期时间date date_nanos


    一、日期格式

    1.1 简介

    JSON没有date类型,但我们可以把以下类型作为日期时间存入ES。

    类型说明
    字符串日期格式的字符串,如"2015-01-01"或"2015/01/01 12:10:30"
    长整型从开始纪元(1970-01-01 00:00:00 UTC)开始的毫秒数
    整型从开始纪元(1970-01-01 00:00:00 UTC)开始的秒数

    上面的UTC(Universal Time Coordinated) 叫做世界统一时间,中国大陆和 UTC 的时差是 + 8 ,也就是 UTC+8。在ES内部,时间以毫秒数(long型)存储,而展现有多种format格式。

    date的格式可以被指定的,如果没有指定,默认“strict_date_optional_time || epoch_millis”
    strict_date_optional_time或者epoch_millis)。

    1.2 什么是epoch_millis?

    • epoch_millis就是从开始纪元(1970-01-01 00:00:00 UTC)开始的毫秒数(long型)
    • 1970以前的时间也可以, 值是负数。

    如下图,2020/8/31 14:57:56是常用的日期格式,它距离1970-01-01 00:00:00 有 1598857076000豪秒。所以可以用1598857076000表示2020/8/31 14:57:56
    在这里插入图片描述

    1.3 什么是strict_date_optional_time?

    strict_date_optional_timedate_optional_time的严格级别,这个严格指的是年份、月份、天必须分别以4位、2位、2位表示,不足两位的话第一位需用0补齐。常见格式如下:

    • yyyy
    • yyyyMM
    • yyyyMMdd
    • yyyyMMddHHmmss
    • yyyy-MM
    • yyyy-MM-dd
    • yyyy-MM-ddTHH:mm:ss dd后面有个T
    • yyyy-MM-ddTHH:mm:ss.SSS
    • yyyy-MM-ddTHH:mm:ss.SSSZ

    工作常见到是yyyy-MM-dd HH:mm:ss,但ES默认不支持这格式,我们可以在format里自定义支持它。上面最后一个里大写的"Z"表示时区。

    二、实验

    2.1 测试date类

    新增一个索引,设置birthday是date格式。

    #ES7去掉了type,所以mappings下面一层不用写“_doc”
    PUT /test_date_index
    {
        "mappings":{
            "properties":{
                "birthday":{
                    "type":"date"
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    测试存入时间格式

    PUT test_date_index/_doc/0
    {
      "birthday":"2020-08"
    }
    
    PUT test_date_index/_doc/1
    {
      "birthday":"2020-08-31"
    }
    
    PUT test_date_index/_doc/2
    {
      "birthday":"2020-08-31T14:32"
    }
    
    PUT test_date_index/_doc/3
    {
      "birthday":"2020-08-31T14:32:11"
    }
    
    PUT test_date_index/_doc/4
    {
      "birthday":"1598857076000"
    }
    
    #1970以前的时间也可以, 值是负数
    PUT test_date_index/_doc/5
    {
      "birthday":"1955-08-31T14:32:11"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    2.2 测试错误的格式:yyyy-MM-ddTHH:mm:s

    因为秒只有1位,左侧没有补0,所以不是合法格式。

    #插入yyyy-MM-ddTHH:mm:s格式
    PUT test_date_index/_doc/3
    {
      "bithday":"2020-08-31T14:32:1"
    }
    
    结果报错:
    "type" : "illegal_argument_exception",
    "reason" : "failed to parse date field [2020-08-31T14:32:1] with format [strict_date_optional_time||epoch_millis]",
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2.3 测试错误的格式:yyyy-MM-dd HH:mm:ss

    #插入yyyy-MM-dd HH:mm:ss格式
    PUT /test_date_index/_doc/3
    {
      "birthday": "2020-03-01 16:29:41"
    }
    
    结果报错:
    "caused_by": {
      "type": "illegal_argument_exception",
      "reason": "Invalid format: \"2020-03-01 16:29:41\" is malformed at \" 16:29:41\""
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    #插入 yyyy-MM-ddTHH:mm:ss格式,ES返回成功
    PUT /test_date_index/_doc/4
    {
      "birthday": "2020-03-01T16:29:41"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    三、混合日期格式

    date类型,还支持一个参数format,它让我们可以自己定制化日期格式。
    比如format配置了格式A||格式B||格式C,插入一个值后,会从左往右匹配,直到有一个格式匹配上。

    举例:你想一个字段同时支持yyyy-MM-dd HH:mm:ssyyyy-MM-ddepoch_millis这3种格式,没有问题,只需在format上设置这3个格式,它们在ES内部都是按照long类型存储的。

    #重建索引
    PUT /test_date_index
    {
        "mappings":{
            "properties":{
                "birthday":{
                    "type":"date",
                    "format":"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
                }
            }
        }
    }
    
    PUT /test_date_index/_doc/1
    {
      "birthday": "2020-03-01 16:29:41"
    }
    
    PUT /test_date_index/_doc/2
    {
      "birthday": "2020-02-29"
    }
    
    #2020/03/01 17:44:09的毫秒级时间戳
    PUT /test_date_index/_doc/3
    {
      "birthday": 1583055849000
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    四、date_nanos,支持纳秒

    date类型支持到毫秒,如果特殊情况下用到纳秒得用date_nanos类型。

    #创建一个index,其date字段是date_nanos类型,支持纳秒
    PUT my_index?include_type_name=true
    {
      "mappings": {
        "_doc": {
          "properties": {
            "date": {
              "type": "date_nanos" 
            }
          }
        }
      }
    }
    
    #和普通的date类型一样,可以存strict_date_optional_time||epoch_millis这些格式的
    #不过在es内部是存的长整型是纳秒单位的
    PUT my_index/_doc/1
    { "date": "2015-01-01" } 
    
    #存一个具体到纳秒的值
    PUT my_index/_doc/2
    { "date": "2015-01-01T12:10:30.123456789Z" } 
    
    #存的是整型,说明是秒,换成日期就是2015/1/1 8:0:0
    #但是在es内部,会以纳秒为单位的long类型存储
    PUT my_index/_doc/3
    { "date": 1420070400 } 
    
    GET my_index/_search
    {
      "sort": { "date": "asc"} 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    五、性能优化

    • 如果不在日期时间字段上做排序、聚合和script脚本操作,可以设置doc_value为false。
    • 如果不在日期时间字段上做检索,只是做展示用,可以设置index为false。

    如果本文对您有帮助,就给亚瑟王点个赞👍吧

  • 相关阅读:
    Flutter 没有完整的生命周期?
    老系统如何重构之最全总结
    导致系统性能失败的10个原因
    宿主机与开发板网络共享
    拒绝加班,程序员开发的效率工具集
    Java开发经典实战!2022 国内知名大厂Java岗面经
    【FPGA零基础学习之旅#13】串口发送模块设计与验证
    WebView2 通过 PuppeteerSharp 实现爬取 王者 壁纸 (案例版)
    ES6--解构赋值-对象(object对象-{}展现 属性:值 )
    JAVA计算机毕业设计医疗病历交互系统Mybatis+系统+数据库+调试部署
  • 原文地址:https://blog.csdn.net/winterking3/article/details/126608510