Elasticsearch时间类型实战

目录

前言

一、核心基础:ES时间类型底层原理

[1.1 ES时间类型唯一标准:date](#1.1 ES时间类型唯一标准:date)

[1.2 ES date 底层核心特性](#1.2 ES date 底层核心特性)

[1.3 ES官方两种标准时间格式](#1.3 ES官方两种标准时间格式)

[1.3.1 通用兼容格式(生产首选)](#1.3.1 通用兼容格式(生产首选))

[1.3.2 自定义本地时间格式](#1.3.2 自定义本地时间格式)

二、ES时间字段Mapping实战配置(两套可用方案)

[2.1 方案一:自定义本地时间格式(适配MySQL原样同步)](#2.1 方案一:自定义本地时间格式(适配MySQL原样同步))

[2.2 方案二:UTC标准格式](#2.2 方案二:UTC标准格式)

[三、Java实体类适配+Java API Client查询实战](#三、Java实体类适配+Java API Client查询实战)

[3.1 适配自定义格式(yyyy-MM-dd HH:mm:ss)](#3.1 适配自定义格式(yyyy-MM-dd HH:mm:ss))

[3.1.1 实体类配置](#3.1.1 实体类配置)

[3.2 适配UTC标准格式(strict_date_optional_time)](#3.2 适配UTC标准格式(strict_date_optional_time))

[3.2.1 实体类配置](#3.2.1 实体类配置)

四、全网高频报错:LocalDateTime反序列化失败(根治方案)

[4.2 报错根因](#4.2 报错根因)

[4.3 分步解决方案](#4.3 分步解决方案)

第一步:引入依赖

第二步:手动配置ES客户端(核心根治)


前言

在实际开发中,Elasticsearch(下文简称ES)时间类型的使用是高频易错点,绝大多数开发者都会遇到时区错乱、序列化报错、MySQL与ES数据同步不一致、Java API查询反序列化失败等问题。

本文结合真实开发场景,从零梳理ES时间类型底层原理、Mapping配置规范、Java实体适配、MySQL数据同步方案、全网最常见报错及根治方案解决所有ES时间相关疑难问题。

一、核心基础:ES时间类型底层原理

1.1 ES时间类型唯一标准:date

ES 中所有时间字段,必须使用 date 类型,绝对禁止使用 keyword、text、long 存储业务时间:

  • 禁止字符串存储:无法范围查询、时间聚合、排序失效

  • 禁止纯long时间戳存储:可读性极差,排查问题困难,可视化查询不友好

1.2 ES date 底层核心特性

无论你传入什么格式的时间,ES底层统一存储【UTC毫秒时间戳】,所有格式化展示、时区适配都是上层封装,底层无字符串概念。

这是ES和MySQL时间设计的本质区别,也是所有时区BUG的根源:

  • MySQL datetime:纯本地时间字符串,无时区属性,绑定服务器时区

  • ES date:绝对时间戳,默认强制识别为UTC 0时区

1.3 ES官方两种标准时间格式

1.3.1 通用兼容格式(生产首选)

适配时间字符串+毫秒时间戳,兼容性最强,官方默认配置:

"format": "strict_date_optional_time||epoch_millis"

支持入库格式:

  • 标准UTC时间:2025-05-08T10:20:30.123Z

  • 秒级UTC时间:2025-05-08T10:20:30Z

  • 毫秒时间戳:1746728430123

1.3.2 自定义本地时间格式

适配MySQL默认时间格式,无时区,仅限全环境东八区场景:

"format": "yyyy-MM-dd HH:mm:ss"

支持入库格式:2025-05-08 10:20:30

自定义的时间格式可以随意自定义,只是搭建可以看一下底层原理,就理解了为什么不太推荐使用。

二、ES时间字段Mapping实战配置(两套可用方案)

本文提供实战偷懒方案(中小企业) 和标准化规范方案(大厂生产),按需选用。

2.1 方案一:自定义本地时间格式(适配MySQL原样同步)

适用场景:国内单体项目、全服务器东八区、无海外业务、无需跨时区统计

优点:MySQL数据无需转换,同步代码极简,开发效率高

缺点:不支持跨时区,扩展性差

复制代码
PUT /order_index_001
{
  "settings": {
    "number_of_replicas": 0
  },
  "mappings": {
    "properties": {
      "order_id": { "type": "keyword" },
      "price": { "type": "scaled_float", "scaling_factor": 100 },
      "pay_num": { "type": "integer" },
      "order_time": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss" },
      "category": { "type": "keyword" }
    }
  }
}

2.2 方案二:UTC标准格式

适用场景:微服务、分布式项目、上云项目、有海外业务、大数据统计

优点:无时区BUG、全球统一、支持所有时间查询/聚合、扩展性拉满

复制代码
PUT /order_index_001
{
  "settings": {
    "number_of_replicas": 0
  },
  "mappings": {
    "properties": {
      "order_id": { "type": "keyword" },
      "price": { "type": "scaled_float", "scaling_factor": 100 },
      "pay_num": { "type": "integer" },
      "order_time": { "type": "date", "format": "strict_date_optional_time||epoch_millis" },
      "category": { "type": "keyword" }
    }
  }
}

三、Java实体类适配+Java API Client查询实战

下面的例子中展示了使用不同的时间格式,Java实体类的类型。

3.1 适配自定义格式(yyyy-MM-dd HH:mm:ss)

3.1.1 实体类配置

对应Mapping无时区格式,使用 LocalDateTime,必须加格式化注解

java 复制代码
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.time.LocalDateTime;

@Data
public class OrderIndex {
    private String order_id;
    private Double price;
    private Integer pay_num;
    private String category;

    // 格式必须与ES Mapping完全一致
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime order_time;
}

3.2 适配UTC标准格式(strict_date_optional_time)

3.2.1 实体类配置

对应ES UTC时间,使用 Instant(绝对UTC时间,无时区BUG)

java 复制代码
import lombok.Data;
import java.time.Instant;

@Data
public class OrderIndex {
    private String order_id;
    private Double price;
    private Integer pay_num;
    private String category;

    // 标准UTC时间,无需格式化注解
    private Instant order_time;
}

四、全网高频报错:LocalDateTime反序列化失败(根治方案)

复制代码

co.elastic.clients.json.JsonpMappingException: Error deserializing co.elastic.clients.elasticsearch.core.search.Hit: jakarta.json.JsonException: Jackson exception Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type `java.time.LocalDateTime` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling

4.2 报错根因

很多同学只加依赖仍报错,核心原因:

  • Spring默认ObjectMapper支持Java8时间类型,但ES Java Client拥有独立的ObjectMapper

  • ES客户端默认未注册Java8时间模块,无法解析LocalDateTime/LocalDate

4.3 分步解决方案

第一步:引入依赖

XML 复制代码
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
</dependency>

第二步:手动配置ES客户端(核心根治)

手动为ES独立的ObjectMapper注册时间模块,彻底解决解析失败问题

如果大家使用的是安全模式下的es连接,可以查看博主的文章:

Java 连接 Elasticsearch 8.x 安全模式实战:证书校验与 ApiKey 认证全解析_elasticsearch 不加spring 连接es服务 ssl校验-CSDN博客

上述文中中的连接时没有配置时间的,大家在结合这个文章中的配置,进行一下时间模块的注册就可以了。

java 复制代码
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.elasticsearch.client.RestClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class EsClientConfig {

    @Bean
    public ElasticsearchClient elasticsearchClient(RestClient restClient) {
        // 注册Java8时间模块,支持LocalDateTime/Instant解析
        ObjectMapper objectMapper = new ObjectMapper()
                .registerModule(new JavaTimeModule());
        JacksonJsonpMapper mapper = new JacksonJsonpMapper(objectMapper);
        ElasticsearchTransport transport = new RestClientTransport(restClient, mapper);
        return new ElasticsearchClient(transport);
    }
}
相关推荐
shuoshuohaohao2 小时前
MyBatis 小知识点
java·spring·mybatis
海上小飞龙2 小时前
【KMP算法-下篇】同一道题:Java 库函数 2600 微秒,手写 KMP 16 微秒
java·开发语言·算法
johnsong3 小时前
当决策成为免费商品:思维成本崩溃背后的治理真空
大数据·人工智能
谢亮_vipxieliang3 小时前
泛型擦除、通配符与 PECS 一次讲透
java·面试
八解毒剂3 小时前
【计组】中央处理器CPU
java·开发语言·计算机组成原理
数字新视界3 小时前
动环监控系统优化数据中心管理,提升环境监测与安全效率
大数据·人工智能·数据中心·微模块机房·模块化机房
zhenaibo5213 小时前
如何向导师请教问题,才能得到有效建议?
大数据·人工智能·深度学习
生活愉甜4 小时前
森马SEMIR LAB全球首家概念店落地武康路,“WUKANG368”新地标就位
大数据·人工智能
乐迪信息4 小时前
港口船舶逆行怎么管?AI防爆摄像机搭载智能检测算法
大数据·人工智能·深度学习·算法·计算机视觉
打工仔折腾 AI4 小时前
工业场景下时序库与实时计算一体化架构选型实践对比
java·开发语言·后端·python·性能优化·架构·ai agent 实战