Date 类型
在你没有定义索引里面字段的类型时,Elasticsearch 会根据你写入的字段的内容动态去判定字段的数据类型,这种自动映射的机制有缺陷,,比如在 Elasticsearch 中没有隐式类型转换,所以在自动映射的时候就会把字段映射为较宽的数据类型。比如你写入一个数字 50,系统就会自动给你映射成 long 类型,而不是 int 。一般企业中用于生产的环境都是使用手工映射,能保证按需创建以节省资源和达到更高的性能。
案例
在kinaba中执行下面内容
POST testdb/_bulk
{"index":{}}
{"title": "文章标题","createTime": "2023-12-13 17:10:20"}
然后查询当前索引 testdb 的mapping,执行 GET testdb
,会看到 createTime 的数据类型是 text.
原因
原因就在于 elasticsearch 对时间类型的格式的要求是绝对严格的。要求必须是一个标准的 UTC 时间类型。上述字段的数据格式如果想要使用,就必须使用yyyy-MM-ddTHH:mm:ssZ
格式(其中T个间隔符,Z代表 0 时区),以下均为错误的时间格式(均无法被自动映射器识别为日期时间类型):
yyyy-MM-dd HH:mm:ss
yyyy-MM-dd
时间戳
注意:需要注意的是时间说是必须的时间格式,但是需要通过 手工映射 方式在索引创建之前指定为日期类型,使用自动映射器无法映射为日期类型。
手工设置时间类型
创建索引:
PUT testdb
{
"mappings": {
"properties": {
"createTime": {
"type": "date"
}
}
}
}
插入数据
POST testdb/_bulk
{"index":{}}
{"title": "文章标题1","createTime": "2023-12-13 17:10:20"}
{"index":{}}
{"title": "文章标题2","createTime": "1702458941"}
{"index":{}}
{"title": "文章标题3","createTime": "2023-12-13T17:10:20Z"}
{"index":{}}
{"title": "文章标题4","createTime": "2023-12-1T17:10:20Z"}
{"index":{}}
{"title": "文章标题5","createTime": "2023-12-13"}
执行结果:
{
"took" : 196,
"errors" : true,
"items" : [
{
"index" : {
"_index" : "testdb",
"_type" : "_doc",
"_id" : "cYl4YowBzu9UbbVthrUM",
"status" : 400,
"error" : {
"type" : "mapper_parsing_exception",
"reason" : "failed to parse field [createTime] of type [date] in document with id 'cYl4YowBzu9UbbVthrUM'. Preview of field's value: '2023-12-13 17:10:20'",
"caused_by" : {
"type" : "illegal_argument_exception",
"reason" : "failed to parse date field [2023-12-13 17:10:20] with format [strict_date_optional_time||epoch_millis]",
"caused_by" : {
"type" : "date_time_parse_exception",
"reason" : "date_time_parse_exception: Failed to parse with all enclosed parsers"
}
}
}
}
},
{
"index" : {
"_index" : "testdb",
"_type" : "_doc",
"_id" : "col4YowBzu9UbbVthrUM",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1,
"status" : 201
}
},
{
"index" : {
"_index" : "testdb",
"_type" : "_doc",
"_id" : "c4l4YowBzu9UbbVthrUM",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"_seq_no" : 1,
"_primary_term" : 1,
"status" : 201
}
},
{
"index" : {
"_index" : "testdb",
"_type" : "_doc",
"_id" : "dIl4YowBzu9UbbVthrUM",
"status" : 400,
"error" : {
"type" : "mapper_parsing_exception",
"reason" : "failed to parse field [createTime] of type [date] in document with id 'dIl4YowBzu9UbbVthrUM'. Preview of field's value: '2023-12-1T17:10:20Z'",
"caused_by" : {
"type" : "illegal_argument_exception",
"reason" : "failed to parse date field [2023-12-1T17:10:20Z] with format [strict_date_optional_time||epoch_millis]",
"caused_by" : {
"type" : "date_time_parse_exception",
"reason" : "date_time_parse_exception: Failed to parse with all enclosed parsers"
}
}
}
}
},
{
"index" : {
"_index" : "testdb",
"_type" : "_doc",
"_id" : "dYl4YowBzu9UbbVthrUM",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"_seq_no" : 2,
"_primary_term" : 1,
"status" : 201
}
}
]
}
结论:
写入成功的是:
1702458941
2023-12-13T17:10:20Z
2023-12-13
写入失败的是:
2023-12-13 17:10:20
2023-12-1T17:10:20Z
- 对于
yyyy-MM-dd HH:mm:ss
或2023-12-1T17:10:20Z
,ES 的自动映射器完全无法识别,即便是事先声明日期类型,数据强行写入也会失败。 - 对于时间戳和yyyy-MM-dd这样的时间格式,ES 自动映射器无法识别,但是如果事先说明了日期类型是可以正常写入的。
- 对于标准的日期时间类型是可以正常自动识别为日期类型,并且也可以通过手工映射来实现声明字段类型。