Spring ElasticSearch:如何在父文档中存储完整子对象
问题根因
出现仅存储student.id的问题,核心是两个配置错误:
Student类继承了携带@Id注解的Common父类,Spring Data Elasticsearch 的字段映射器会自动将带@Id属性的类型识别为独立文档实体,而非普通内嵌对象,序列化时仅提取id字段存入Table,其余属性全部被过滤。student字段上加的includeInParent = true是ES父子Join关系的专属配置,和内嵌对象需求完全无关,反而会干扰映射逻辑判定。
修复方案
1. 调整Table类的字段注解
移除错误的关联配置,明确指定内嵌对象类型:
@Getter @Setter @Document(indexName = "table") public class Table extends Common { // 明确指定为普通Object类型,移除includeInParent参数 @Field(type = FieldType.Object) private Student student; private String attends; }
2. 解决Student被误判为独立文档的问题
根据业务场景二选一:
- 如果Student仅作为Table的内嵌对象使用,无需单独存储ES索引
直接让Student不再继承带@Id的Common,自定义独立id字段,彻底避免被映射器判定为独立文档:@Getter @Setter public class Student { private String id; private String name; private String phone; private String password; @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "yyyy-MM-dd'T'HH:mm:ss") private LocalDateTime createdAt; } - 如果Student还需在其他场景作为独立ES文档使用,必须保留继承Common
给Student类添加@Document注解,设置不自动创建无用索引,让映射器将其识别为可序列化的POJO而非关联引用:// 标记为文档但禁止自动创建索引,不影响内嵌使用 @Getter @Setter @Document(indexName = "ignore_student", createIndex = false) public class Student extends Common { // 原有属性保持不变 }
3. 修正旧索引映射
ES的索引映射一旦创建,子字段无法随意修改。如果之前已经创建过table索引,需要先删除旧索引,再重新启动应用让Spring Data自动生成符合预期的映射,再插入数据。
补充说明
- 若后续需要对内嵌的Student属性做精确关联查询,可将
@Field的类型改为FieldType.Nested,普通存储场景下FieldType.Object足够使用。 - 不要使用
FieldType.Auto声明内嵌对象,自动推断的映射很容易出现不符合预期的问题,明确指定类型更稳妥。
内容的提问来源于stack exchange,提问作者Abraham Arnold
相关产品推荐
相关产品推荐

