Spring Data Elasticsearch中如何注册自定义转换器适配@GeoShapeField?
解决Spring Data Elasticsearch 5中@GeoShapeField支持Envelope等扩展类型的问题
核心思路
Spring Data Elasticsearch的GeoConverters默认仅处理标准GeoJSON类型,要支持Envelope这类ES兼容的非标准类型,需自定义转换器并通过配置让@GeoShapeField字段优先选用这些转换器。
步骤1:编写自定义转换器
针对Map<String, Object>与ES的GeoShape类型(如Envelope),分别实现写入、读取转换器:
写入转换器(Map转ES可识别的GeoShape格式)
@Component public class MapToEnvelopeGeoShapeConverter implements Converter<Map<String, Object>, GeoJson> { @Override public GeoJson convert(Map<String, Object> source) { // 根据GML解析后的Map结构判断是否为Envelope类型 if ("Envelope".equals(source.get("type"))) { List<List<Double>> coordinates = (List<List<Double>>) source.get("coordinates"); // 构造ES支持的Envelope GeoShape return GeoJsonEnvelope.of( GeoJsonPoint.of(coordinates.get(0).get(0), coordinates.get(0).get(1)), GeoJsonPoint.of(coordinates.get(1).get(0), coordinates.get(1).get(1)) ); } // 非Envelope类型交给默认转换器处理 return new GeoConverters.MapToGeoJsonConverter().convert(source); } }
读取转换器(ES返回的GeoShape转Map)
@Component public class EnvelopeGeoShapeToMapConverter implements Converter<GeoJson, Map<String, Object>> { @Override public Map<String, Object> convert(GeoJson source) { if (source instanceof GeoJsonEnvelope) { GeoJsonEnvelope envelope = (GeoJsonEnvelope) source; Map<String, Object> result = new HashMap<>(); result.put("type", "Envelope"); result.put("coordinates", Arrays.asList( Arrays.asList(envelope.getLowerLeft().getX(), envelope.getLowerLeft().getY()), Arrays.asList(envelope.getUpperRight().getX(), envelope.getUpperRight().getY()) )); return result; } // 非Envelope类型交给默认转换器处理 return new GeoConverters.GeoJsonToMapConverter().convert(source); } }
步骤2:注册自定义转换器到ES配置
通过ElasticsearchCustomConversions注册自定义转换器,让Spring Data Elasticsearch识别并优先使用:
@Configuration public class ElasticsearchConfig extends AbstractElasticsearchConfiguration { @Override public RestHighLevelClient elasticsearchClient() { // 此处配置你的ES客户端,示例为本地默认地址 return RestClients.create(ClientConfiguration.create("localhost:9200")).rest(); } @Override protected ElasticsearchCustomConversions elasticsearchCustomConversions() { return new ElasticsearchCustomConversions(Arrays.asList( new MapToEnvelopeGeoShapeConverter(), new EnvelopeGeoShapeToMapConverter() )); } }
步骤3:确保转换器优先级
Spring Data Elasticsearch会优先匹配自定义转换器——因为自定义转换器的泛型匹配更具体(直接针对Envelope场景),会覆盖GeoConverters中的默认逻辑。遇到标准GeoJSON类型时,转换器会自动降级使用默认处理逻辑,不破坏现有功能。
关键注意事项
- 需根据实际GML解析后的Map结构调整Envelope的判断逻辑,确保能准确识别目标类型。
- 确认Spring Data Elasticsearch 5与ES 8的版本兼容性,
GeoJsonEnvelope是两者均支持的类型。
内容的提问来源于stack exchange,提问作者Wang Tang
相关产品推荐
相关产品推荐

