Elasticsearch教程(20) 详解mapping之date date_nanos

1 简介

  • JSON没有date数据类型,但我们可以把以下类型的数据作为日期时间存入ES。
  • 然而在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内部,时间以毫秒数的UTC存储。

2 日期时间的格式

date的格式可以被指定的,如果没有特殊指定,默认格式是"strict_date_optional_time||epoch_millis"
这段话可以理解为格式为strict_date_optional_time或者epoch_millis

2.1 什么是epoch_millis?

epoch_millis就是从开始纪元(1970-01-01 00:00:00 UTC)开始的毫秒数-长整型。
如下图,2020/8/31 14:57:56是我们常用的日期格式,它距离1970-01-01 00:00:00 有 1598857076000豪秒。所以可以用长整型1598857076000表示2020/8/31 14:57:56。
在这里插入图片描述

2.2 什么是strict_date_optional_time?

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

常见的格式有如下:

  • yyyy
  • yyyyMM
  • yyyyMMdd
  • yyyyMMddHHmmss
  • yyyy-MM
  • yyyy-MM-dd
  • yyyy-MM-ddTHH:mm:ss
  • yyyy-MM-ddTHH:mm:ss.SSS
  • yyyy-MM-ddTHH:mm:ss.SSSZ

工作常见到是"yyyy-MM-dd HH:mm:ss",但是ES是不支持这格式的,需要在dd后面加个T,这个是固定格式。上面最后一个里大写的"Z"表示时区。

2.3 测试录入date类型

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

#ES7去掉了type,所以mappings下面一层不用写“_doc”
PUT /test_date_index
{
    
    
    "mappings":{
    
    
        "properties":{
    
    
            "birthday":{
    
    
                "type":"date"
            }
        }
    }
}

测试存入时间格式

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"
}

查询数据-按照日期正序排序

扫描二维码关注公众号,回复: 12882543 查看本文章
GET test_date_index/_search
{
    
    
  "sort": [
    {
    
    
      "birthday": {
    
    
        "order": "asc"
      }
    }
  ]
}

从返回结果可以看出上面的日期格式是正确的。

  "hits" : [
      {
    
    
        "_index" : "test_date_index",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : null,
        "_source" : {
    
    
          "birthday" : "1955-08-31T14:32:11"
        },
        "sort" : [
          -452424469000
        ]
      },
      {
    
    
        "_index" : "test_date_index",
        "_type" : "_doc",
        "_id" : "0",
        "_score" : null,
        "_source" : {
    
    
          "birthday" : "2020-08"
        },
        "sort" : [
          1596240000000
        ]
      },
      {
    
    
        "_index" : "test_date_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : null,
        "_source" : {
    
    
          "birthday" : "2020-08-31"
        },
        "sort" : [
          1598832000000
        ]
      },
      {
    
    
        "_index" : "test_date_index",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : null,
        "_source" : {
    
    
          "birthday" : "2020-08-31T14:32:11"
        },
        "sort" : [
          1598884331000
        ]
      }
    ]

2.4 测试错误的格式: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]",

2.5 测试错误的格式: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\""
}
#插入 yyyy-MM-ddTHH:mm:ss格式,ES返回成功
PUT /test_date_index/_doc/4
{
    
    
  "birthday": "2020-03-01T16:29:41"
}

2.6 你就是想用yyyy-MM-dd HH:mm:ss?

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

#先删除索引
DELETE test_date_index

#重建索引
PUT /test_date_index
{
    
    
    "mappings":{
    
    
        "properties":{
    
    
            "birthday":{
    
    
                "type":"date",
                "format":"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
            }
        }
    }
}

#2020/03/01 17:44:09的毫秒级时间戳
PUT /test_date_index/_doc/1
{
    
    
  "birthday": 1583055849000
}

PUT /test_date_index/_doc/2
{
    
    
  "birthday": "2020-03-01 16:29:41"
}

PUT /test_date_index/_doc/3
{
    
    
  "birthday": "2020-02-29"
}
#上面3条语句都可以保存成功

3 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"} 
}

猜你喜欢

转载自blog.csdn.net/winterking3/article/details/108287167