当前位置: 首页 > article >正文

Elasticsearch 8.13.4 LocalDateTime类型转换问题

框架背景

springboot 3.3.1+elasticseach8.13.4+spring-data-elasticsearch5.3.1(其实只要用了springboot3.3.1 上下两个的版本都在里面绑死了)

问题描述

使用spring-data-elasticsearch操作es,当字段增加映射注解,其实如果是日期类型,你不加默认也给你映射成date了

@Field(type = FieldType.Date)

可以正常保存成功,但查询时会报错

org.springframework.data.elasticsearch.core.convert.ConversionException: Unable to convert value ‘2024-08-30’ to java.time.LocalDateTime for property ‘createTime’

通过kibana查看数据

数据查询发现保存的数据格式是 “2024-08-30”,导致读取时解析失败

解决方案使用自定义的转换器,我这里是将LocalDateTime保存为时间戳,读取的时候再转为LocalDateTime

以下是配置类(我是自定义了一个starer,所以用了@AutoConfiguration)

package cn.iocoder.centralstore.framework.es.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.data.elasticsearch.core.mapping.PropertyValueConverter;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;

/***
 * @Description: 处理 Elasticsearch 中 LocalDateTime 与时间戳之间的转换
 * 将 LocalDateTime 写入为时间戳,读取时将时间戳转换为 LocalDateTime。
 * @Author: TaoYuan
 * @Date: 2024/8/29
 */
@AutoConfiguration
@Slf4j
public class CentralstoreLocalDateTimeConverter implements PropertyValueConverter {

    // 使用系统默认时区
    private static final ZoneId ZONE_ID = ZoneId.systemDefault();
    
    @Override
    public Object write(Object value) {
        if (value instanceof LocalDateTime localDateTime) {
            Instant instant = localDateTime.atZone(ZONE_ID).toInstant();
            long timestamp = instant.toEpochMilli();
            log.info("将 LocalDateTime [{}] 转换为时间戳 [{}]", localDateTime, timestamp);
            return timestamp;
        } else {
            String errorMessage = String.format("写入操作接收到非 LocalDateTime 值: [%s], 类型: [%s]", value, value.getClass().getName());
            log.error(errorMessage);
            throw new IllegalStateException(errorMessage);
        }
    }

    @Override
    public Object read(Object value) {
        if (value instanceof Long timestamp) {
            LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZONE_ID);
            log.info("将时间戳 [{}] 转换为 LocalDateTime [{}]", timestamp, localDateTime);
            return localDateTime;
        } else {
            String errorMessage = String.format("无法将值 '值: [%s], 类型: [%s] 解析为 LocalDateTime", value,value.getClass().getName());
            log.error(errorMessage);
            throw new IllegalStateException(errorMessage);
        }
    }
}

字段增加注解

@Field(type = FieldType.Date)
@ValueConverter(CentralstoreLocalDateTimeConverter.class)
private LocalDateTime createTime;```

至此,插入数据和查询数据LocalDateTime类型就搞定了。其实里面还有很多细节,但是大部分估计跟我一样,只想着找到解决方案,不去想为什么会这样。所以就懒得继续深讲了。

还有很多坑,比如使用雪花算法生成的Id是19位,存入es后后两位精度丢失,这个处理起来最简单的办法就是使用String类型的作为id。或者跟上面一样 增加一个Long类型的转换器,转为String ,读取的时候再转换为Long。这个我还没有尝试,只是目前改了一下id的数据类型。

到现在为止仍然没有整合完,还有一堆坑等着我,次奥!!!次奥!!!次奥!!!


http://www.kler.cn/a/282833.html

相关文章:

  • layui的table组件中,对某一列的文字设置颜色为浅蓝怎么设置
  • 38配置管理工具(如Ansible、Puppet、Chef)
  • 【JavaScript】为 setInterval()定义变量,存储ID
  • K8S单节点部署及集群部署
  • HTTP常见的状态码有哪些,都代表什么意思
  • 手动实现promise的all,race,finally方法
  • 使用seamless-scroll-v3 实现无缝滚动,自动轮播平滑的滚动效果
  • Linux系统——服务器长时间训练不间断指令(nohup的简单用法)
  • PsConvertToGuiThread函数调用前传
  • 力扣第二阶段Days34
  • AI在医学领域:GluFormer一种可泛化的连续血糖监测数据分析基础模型
  • 自动化任务工具 | zTasker v1.97.1 绿色版
  • [Hive]四、Hive On Tez
  • 私域流量升级下的新机遇——“开源 AI 智能名片S2B2C 商城小程序”与新兴技术的融合
  • ARM/Linux嵌入式面经(二七):韶音
  • Java LeetCode 练习
  • pmp证书为何会被骂?他真的就是个垃圾证书?
  • 鸿蒙HarmonyOS开发实战: 页面传值跳转
  • Linux CMake根据环境变量和编译选项,编译多模块
  • k8s集群搭建
  • 四个版本的双向链表(C++,C++ CLI, C#, Java)
  • 奇安信渗透测试岗位三面经验分享
  • SpringBoot集成EasyExcel实现Excel文件导入/出
  • 计算机基础复习8.29
  • 力扣top300:3. 无重复字符的最长子串
  • Prompt-Tuning 和 LoRA大模型微调方法区别