場景重現
在使用 MyBatis/Mybatis-Plus 框架對 MySQL 操作時習慣了字段名小駝峰映射,然而在操作 Elasticsearch 時發現字段名沒有小駝峰映射。
解決方法
1. 使用 `ObjectMapper` 手動轉換:
這是最直接也最常用的方法。 在 Spring Boot 應用中使用 `ObjectMapper` 將從 Elasticsearch 獲取的數據進行轉換,將下劃線命名轉換為小駝峰命名。
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 {@Autowiredprivate ObjectMapper objectMapper; // 通過 @Bean 配置 ObjectMapperpublic 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:
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 {@Beanpublic ObjectMapper objectMapper() {ObjectMapper objectMapper = new ObjectMapper();// 可以根據需要配置 ObjectMapper 的其他屬性return objectMapper;}
}
2. 使用 Elasticsearch 的 `field_alias` (推薦但ES版本要支持):
從 Elasticsearch 7.0 開始,引入了 `field_alias`。 你可以利用這個功能,在 Elasticsearch 索引的 Mapping 中定義字段別名,將下劃線命名的字段映射到小駝峰命名的字段。
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 類的字段上。
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
?注解是一個好主意。- 避免自定義客戶端和插件:?除非你有非常特殊的需求,否則不建議使用自定義客戶端和插件,因為它們維護成本很高。