在Elasticsearch中,时间类型是一个非常容易踩坑的数据类型,不按照严格的时间格式,会被识别成text类型
ES对时间类型的格式的要求是绝对严格的。要求必须是一个标准的UTC时间类型 必须使用yyyy-MM-ddTHH:mm:ssZ格式(其中T个间隔符,Z代表 0 时区)
需要通过手工映射方式在索引创建之前指定为日期类型,使用自动映射器无法映射为日期类型。
“format”: “yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis”,这样就可以避免因为数据格式不统一而导致数据无法写入的窘境
PUT test_index
{
"mappings": {
"properties": {
"time": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
}
}
如果版本在7.11.x及以上版本可以有下面的方案
❗❗ 实测可用,但做聚合查询会有性能影响,推荐开始时候就定义好准确的字段
GET task1/_search
{
"size": 0,
"runtime_mappings": {
"day_of_week": {
"type": "keyword",
"script": "emit(doc['time'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL,Locale.ROOT))"
},
"time": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
},
"aggs": {
//1:按照周统计地震信息,也就是每周有几天地震了
"week_agg": {
"date_histogram": {
"field": "time",
"calendar_interval": "week"
},
"aggs": {
"week_avg_magnitude": {
"avg": {
"field": "magnitude"
}
}
}
},
//一周中的每一天的震级
"day_of_week_magnitude":{
"terms": {
"field": "day_of_week"
},
"aggs": {
//2: 一周中每一天的平均地震等级
"day_of_week_avg_magnitude": {
"avg": {
"field": "magnitude"
}
}
}
}
}
}
此段代码中,其核心代码如下
"runtime_mappings": {
"day_of_week": {
"type": "keyword",
"script": "emit(doc['time'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL,Locale.ROOT))"
},
"time": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
其在runtime_mappings 中定义了两个“新字段”,即day_of_week和time,其中day_of_week利用运行时字段中执行脚本进行动态计算,从而得出每天分别是一周内的星期几。这种用法可用于各种其他复杂的运算。
而time字段则是对原有字段进行重新映射,改变其原有字段的类型和其他属性,如format,使其原本不支持的时间类型变为支持。
[1] ES 中时间日期类型