ES 中时间日期类型 “yyyy-MM-dd HHmmss” 的完全避坑指南

本文详细剖析了Elasticsearch(ES)中时间日期类型的坑,强调了自动映射时对严格UTC格式的要求。举例说明了非标准格式导致字段被映射为text类型的问题,以及如何通过设置`format`参数解决数据写入困境。同时,提出了在生产环境中面对已有数据类型错误时,不必重新索引,可以利用`runtime_fields`优雅地解决问题。

文章目录

1、ES中的日期类型有何不同

时间和日期类型是我们作为开发每天都会遇到的一种常见数据类型。和Java中有所不同,Elasticsearch 在索引创建之前并不是必须要创建索引的mapping。关系型数据库的思维就是在中写入数据之前,并不强制创建表结构。我们不用事先声明字段名称,字段类型以及长度等属性就可以直接像一个不存在的表中直接写入数据。

Elasticsearch把这种特性称之为dynamic mapping,也就是自动映射。Elasticsearch会根据你写入的字段的内容动态去判定字段的数据类型,不过这种自动映射的机制存在一些缺陷,比如在Elasticsearch中没有隐式类型转换,所以在自动映射的时候就会把字段映射为较宽的数据类型。比如你写入一个数字50,系统就会自动给你映射成long类型,而不是int 。一般企业中用于生产的环境都是使用手工映射,能保证按需创建以节省资源和达到更高的性能。

但是在Elasticsearch中,时间类型是一个非常容易踩坑的数据类型,通过一个例子向大家展示这个时间类型到底有多“坑”!

2、案例

2.1 案例介绍

假如我们有如下索引tax,保存了一些公司的纳税或资产信息,单位为“万元”。当然这里面的数据是随意填写的。多少为数据统计的时间,当前这个例子里。索引达的含义并不重要。关键点在于字段的内容格式。我们看到date字段其中包含了多种日期的格式:“yyyy-MM-dd”,“yyyy-MM-dd”还有时间戳。如果按照dynamic mapping,采取自动映射器来映射索引。我们自然而然的都会感觉字段应该是一个date类型。

POST tax/_bulk
{"index":{}}
{"date": "2021-01-25 10:01:12", "company": "中国烟草", "ratal": 5700000}
{"index":{}}
{"date": "2021-01-25 10:01:13", "company": "华为", "ratal": 4034113.182}
{"index":{}}
{"date": "2021-01-26 10:02:11", "company": "苹果", "ratal": 7784.7252}
{"index":{}}
{"date": "2021-01-26 10:02:
要解决 easy-es 使用 `yyyy-MM-dd HH:mm:ss` 格式的 `date` 时间类型新增数据后,ES 中显示为 `text` 类型的问题,可从以下几个方面着手: ### 1. 检查实体类注解 确保实体类中的日期字段使用了正确的注解,指定日期格式。在 easy-es 中,可使用 `@TableField` 注解来指定日期格式。示例代码如下: ```java import cn.easyes.annotation.TableField; import cn.easyes.annotation.TableId; import cn.easyes.annotation.TableName; import lombok.Data; import java.util.Date; @Data @TableName("your_index_name") public class YourEntity { @TableId private String id; @TableField(fieldType = FieldType.DATE, dateFormat = "yyyy-MM-dd HH:mm:ss") private Date yourDateField; } ``` 在上述代码中,`@TableField` 注解的 `fieldType` 属性指定了字段类型为 `DATE`,`dateFormat` 属性指定了日期格式为 `yyyy-MM-dd HH:mm:ss`。 ### 2. 重建索引 若实体类注解无误,但 ES 中字段类型仍未正确映射,可尝试重建索引。重建索引时,easy-es 会依据实体类的注解重新创建索引映射。示例代码如下: ```java import cn.easyes.core.core.EsMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class YourService { @Autowired private EsMapper<YourEntity> esMapper; public void recreateIndex() { // 删除旧索引 esMapper.deleteIndex(); // 创建新索引 esMapper.createIndex(); } } ``` 在上述代码中,`deleteIndex` 方法用于删除旧索引,`createIndex` 方法用于创建新索引。 ### 3. 检查 ES 配置 确保 ES 客户端配置正确,特别是日期格式的配置。在 Spring Boot 项目中,可在 `application.yml` 或 `application.properties` 文件中配置 ES 客户端。示例配置如下: ```yaml easy-es: address: localhost:9200 date-format: yyyy-MM-dd HH:mm:ss ``` 在上述配置中,`date-format` 属性指定了全局的日期格式。 ### 4. 手动更新映射 若重建索引后问题依旧存在,可尝试手动更新 ES 索引的映射。可使用 ES 的 REST API 或 Java 客户端来更新映射。示例代码如下: ```java import org.elasticsearch.client.Request; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.io.IOException; @Service public class YourMappingService { @Autowired private RestHighLevelClient restHighLevelClient; public void updateMapping() throws IOException { String indexName = "your_index_name"; String mappingJson = "{\"properties\":{\"yourDateField\":{\"type\":\"date\",\"format\":\"yyyy-MM-dd HH:mm:ss\"}}}"; Request request = new Request("PUT", "/" + indexName + "/_mapping"); request.setJsonEntity(mappingJson); restHighLevelClient.performRequest(request, RequestOptions.DEFAULT); } } ``` 在上述代码中,通过 `RestHighLevelClient` 发送 PUT 请求来更新索引的映射。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值