解决 Spring Boot 对 Elasticsearch 字段没有小驼峰映射的问题

场景重现

在使用 MyBatis/Mybatis-Plus 框架对 MySQL 操作时习惯了字段名小驼峰映射,然而在操作 Elasticsearch 时发现字段名没有小驼峰映射。

解决方法

1. 使用 `ObjectMapper` 手动转换:

这是最直接也最常用的方法。 在 Spring Boot 应用中使用 `ObjectMapper` 将从 Elasticsearch 获取的数据进行转换,将下划线命名转换为小驼峰命名。

java 复制代码
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
public class ElasticsearchService {

    @Autowired
    private ObjectMapper objectMapper; // 通过 @Bean 配置 ObjectMapper

    public Map<String, Object> getDocument(String index, String id) {
        // 假设你已经有了从 Elasticsearch 获取文档的方法,这里是模拟
        Map<String, Object> document = new HashMap<>();
        document.put("first_name", "John");
        document.put("last_name", "Doe");

        // 将下划线命名转换为小驼峰命名
        ObjectMapper snakeCaseMapper = new ObjectMapper();
        snakeCaseMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
        ObjectMapper camelCaseMapper = new ObjectMapper();
        camelCaseMapper.setPropertyNamingStrategy(PropertyNamingStrategies.LOWER_CAMEL_CASE);

        try {
            String jsonString = snakeCaseMapper.writeValueAsString(document);
            return camelCaseMapper.readValue(jsonString, Map.class);

        } catch (Exception e) {
            // 处理异常
            e.printStackTrace();
            return null;
        }
    }
}

解释:

• `ObjectMapper` 配置: 在 Spring Boot 应用中,你需要配置一个 `ObjectMapper` Bean。

• `PropertyNamingStrategy`: 通过设置 `PropertyNamingStrategy`,`ObjectMapper` 可以自动将下划线命名转换为小驼峰命名。 这里先使用`snakeCaseMapper`读取,再使用`camelCaseMapper`写出。

• 转换过程: 从 Elasticsearch 获取的数据(`Map`)使用 `ObjectMapper`序列化成 JSON 字符串,然后再反序列化成 `Map`。 在这个过程中,`PropertyNamingStrategy` 会自动进行命名转换。

配置 `ObjectMapper` Bean:

java 复制代码
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ObjectMapperConfig {

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        // 可以根据需要配置 ObjectMapper 的其他属性
        return objectMapper;
    }
}

2. 使用 Elasticsearch 的 `field_alias` (推荐但ES版本要支持):

从 Elasticsearch 7.0 开始,引入了 `field_alias`。 你可以利用这个功能,在 Elasticsearch 索引的 Mapping 中定义字段别名,将下划线命名的字段映射到小驼峰命名的字段。

java 复制代码
PUT my_index
{
  "mappings": {
    "properties": {
      "first_name": {
        "type": "alias",
        "path": "first_name"
      },
      "last_name": {
        "type": "alias",
        "path": "last_name"
      }
    }
  }
}

注意: `field_alias` 只是别名,它仍然需要你存储实际的下划线命名的字段。 这样做的好处是,你可以在查询时使用小驼峰命名,但底层存储仍然是下划线命名。

3. 自定义 Elasticsearch 客户端 (不推荐):

你可以自定义 Elasticsearch 客户端,拦截响应结果,并手动进行字段命名转换。 这通常比较复杂,需要你深入了解 Elasticsearch 客户端的内部机制。不建议使用这种方法,因为它维护成本高。

4. 定义 DTO 类并使用 `@JsonProperty` 注解:

创建一个 DTO 类,对应 Elasticsearch 中的文档结构,并在 DTO 类的字段上使用 `@JsonProperty` 注解,将 Elasticsearch 的字段名映射到 DTO 类的字段上。

java 复制代码
import com.fasterxml.jackson.annotation.JsonProperty;

public class UserDTO {

    @JsonProperty("first_name")
    private String firstName;

    @JsonProperty("last_name")
    private String lastName;

    // Getters and setters
}

然后,从 Elasticsearch 获取数据后,将数据映射到 `UserDTO` 对象。

5. 使用 Elasticsearch 插件 (不推荐):

有一些第三方 Elasticsearch 插件可以自动进行字段命名转换。 但使用插件会增加系统的复杂性,并且可能存在兼容性问题,因此不建议使用。

选择哪种方法?

  • 优先考虑 field_alias (如果你的 Elasticsearch 版本支持): 它是最优雅的解决方案,对现有代码的改动最小。
  • ObjectMapper 手动转换: 如果你无法修改 Elasticsearch 的 Mapping,那么使用 ObjectMapper 是一个不错的选择。 它简单易用,并且可以灵活地控制转换过程。
  • @JsonProperty 注解: 如果你的数据结构相对固定,并且需要将其映射到 DTO 对象,那么使用 @JsonProperty 注解是一个好主意。
  • 避免自定义客户端和插件: 除非你有非常特殊的需求,否则不建议使用自定义客户端和插件,因为它们维护成本很高。
相关推荐
计算机毕设VX:Fegn089529 分钟前
计算机毕业设计|基于springboot + vue蛋糕店管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
没差c1 小时前
springboot集成flyway
java·spring boot·后端
三水不滴1 小时前
Redis 过期删除与内存淘汰机制
数据库·经验分享·redis·笔记·后端·缓存
编程彩机2 小时前
互联网大厂Java面试:从Java SE到大数据场景的技术深度解析
java·大数据·spring boot·面试·spark·java se·互联网大厂
笨蛋不要掉眼泪2 小时前
Spring Boot集成LangChain4j:与大模型对话的极速入门
java·人工智能·后端·spring·langchain
像少年啦飞驰点、3 小时前
零基础入门 Spring Boot:从“Hello World”到可上线微服务的完整学习指南
java·spring boot·微服务·编程入门·后端开发
indexsunny5 小时前
互联网大厂Java面试实战:从Spring Boot到微服务架构的技术问答解析
java·spring boot·redis·微服务·kafka·jwt·flyway
sheji34165 小时前
【开题答辩全过程】以 基于SpringBoot的疗养院管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
短剑重铸之日5 小时前
《设计模式》第六篇:装饰器模式
java·后端·设计模式·装饰器模式