ElasticsearchRepository查询返回空列表 ES有数据无法解析为Java对象
问题根因
你返回结果为空的核心原因是Spring Data Elasticsearch的反序列化类型不匹配:
你ES返回的文档_source中内置的_class字段值为com.asdf.asdf.service.data.prodimb.ProdIMB,但你用于接收查询结果的类是MaildatIMB,默认配置下Spring Data ES会严格校验_class值和目标类的全限定名是否一致,匹配不上的文档会被直接跳过,不会转换成Java对象,最终就会返回空列表。
解决方案
你可以根据自己的业务场景选以下任意一种方式修复:
方案1:统一存储和查询的实体类
如果是代码重构后类名/路径发生了变更,或者误用了不同的类做数据写入和查询,直接统一使用同一个实体类操作ES即可,这是最稳妥的方案。
方案2:添加类型别名
如果你确实需要用MaildatIMB类映射原有ProdIMB类写入的数据,可以直接在MaildatIMB类上添加@TypeAlias注解,指定和ES中存储一致的_class值:
@Document(indexName = Indices.MAILDAT_IMB,shards = 2) @TypeAlias("com.asdf.asdf.service.data.prodimb.ProdIMB") // 加这一行 public class MaildatIMB extends IMBDocument { // 原有代码保持不变 }
方案3:全局禁用类型校验(不推荐)
如果你需要忽略_class字段的校验,只要字段结构匹配就可以反序列化,可以在ES配置类中自定义MappingElasticsearchConverter,关闭类型读取限制:
@Bean @Override public ElasticsearchCustomConversions elasticsearchCustomConversions() { return new ElasticsearchCustomConversions(Collections.emptyList()); } @Bean @Override public MappingElasticsearchConverter elasticsearchEntityMapper( ElasticsearchMappingContext mappingContext, ElasticsearchCustomConversions conversions) { MappingElasticsearchConverter converter = new MappingElasticsearchConverter(mappingContext); converter.setConversions(conversions); // 关闭类型校验 converter.setTypeMapper(new DefaultElasticsearchTypeMapper(DefaultElasticsearchTypeMapper.DEFAULT_TYPE_FIELD, Collections.emptyList())); return converter; }
其他需要确认的检查点
- 确认基类
IMBDocument存在公共的无参构造函数,否则反序列化时无法实例化对象也会返回空 - 确认实体类的所有字段的
@Field注解类型和ES索引中的实际字段类型匹配,避免字段转换失败
内容的提问来源于stack exchange,提问作者fudge
相关产品推荐
相关产品推荐

