解决 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 注解是一个好主意。
  • 避免自定义客户端和插件: 除非你有非常特殊的需求,否则不建议使用自定义客户端和插件,因为它们维护成本很高。
相关推荐
码事漫谈几秒前
性能提升11.4%!C++ Vector的reserve()方法让我大吃一惊
后端
AI分享猿11 分钟前
Java后端实战:SpringBoot接口遇异常请求,轻量WAF兼顾安全与性能
java·spring boot·安全
稚辉君.MCA_P8_Java21 分钟前
Gemini永久会员 Java中的四边形不等式优化
java·后端·算法
稚辉君.MCA_P8_Java32 分钟前
通义 插入排序(Insertion Sort)
数据结构·后端·算法·架构·排序算法
二进制coder34 分钟前
Git Fork 开发全流程教程
大数据·git·elasticsearch
q***697742 分钟前
【Spring Boot】统一数据返回
java·spring boot·后端
v***598343 分钟前
DeepSeek API 调用 - Spring Boot 实现
windows·spring boot·后端
Hollis Chuang44 分钟前
Spring Boot 4.0 正式发布,人麻了。。。
java·spring boot·后端·spring
Moshow郑锴1 小时前
实战分享:用 SpringBoot-API-Scheduler 构建 API 监控闭环 —— 从断言验证到智能警报
java·spring boot·后端·任务调度
金融数据出海2 小时前
日本股票市场渲染 KlineCharts K 线图
前端·后端