Spring Elasticsearch中Map<String,String>索引查询报错问题求助
问题描述
我有一个包含Map<String, String>字段的实体类:
@Document(indexName = "custom-creative-template") @Setting(settingPath = "/elasticsearch/custom-creative-template-index.json") public class CustomCreativeTemplateIndexDto { Map<String, String> customValues; }
查询该索引数据时出现如下错误:
org.springframework.data.mapping.MappingException: Couldn't find PersistentEntity for type java.lang.String!
但改用Map<String, Object>时可以正常工作。以下是该索引的Settings文件:
{ "index": { "analysis": { "normalizer": { "sortable": { "filter": [ "lowercase" ] } } } } }
我尝试在@Field注解中设置FieldType为Text和Flattened,但仍出现相同错误。索引的Mappings如下:
{ "custom-creative-template": { "mappings": { "properties": { "_class": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "customValues": { "properties": { "offerBullets": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "offerDescription": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } }, "key": { "type": "long" }, "name": { "type": "text", "fields": { "sort": { "type": "keyword", "normalizer": "sortable" } } } } } } }
解决方案
这个问题的核心是Spring Data Elasticsearch在处理Map<String, String>时,会错误地把字符串值当成需要映射的实体类型,而非简单的字符串。以下是几种可行的解决办法:
1. 给customValues标注@Field(type = FieldType.Object)
直接明确告诉Spring Data Elasticsearch,这个字段是对象类型的映射,不需要把内部的字符串值解析为实体:
@Document(indexName = "custom-creative-template") @Setting(settingPath = "/elasticsearch/custom-creative-template-index.json") public class CustomCreativeTemplateIndexDto { @Field(type = FieldType.Object) Map<String, String> customValues; }
2. 配合动态映射注解使用
如果customValues是动态生成的字段,可以加上@DynamicMapping注解,避免框架对内部值做实体解析:
@Document(indexName = "custom-creative-template") @Setting(settingPath = "/elasticsearch/custom-creative-template-index.json") public class CustomCreativeTemplateIndexDto { @Field(type = FieldType.Object) @DynamicMapping(DynamicMappingValue.TRUE) Map<String, String> customValues; }
3. 将ES Mapping改为flattened类型
把customValues的Mapping类型改成flattened,ES会把整个Map作为单一字段处理,Spring Data也不会再把内部值当成独立实体。修改后的Mapping片段:
"customValues": { "type": "flattened" }
同时实体类字段对应标注:
@Field(type = FieldType.Flattened) Map<String, String> customValues;
4. 自定义类型转换器
如果以上方法都不适用,可以实现自定义的Converter,手动处理Map<String, String>与ES存储格式的转换,绕过框架的实体映射逻辑。
内容的提问来源于stack exchange,提问作者murohima_1
相关产品推荐
相关产品推荐

