代码之家  ›  专栏  ›  技术社区  ›  Thomas Feiler

如何在应用程序启动时正确解决“无法添加指向已存在类型的\u父字段,该类型尚未为父字段”的问题

  •  0
  • Thomas Feiler  · 技术社区  · 7 年前

    我遇到了一个问题,我的Elasticsearch文档索引创建在启动时失败,原因是“java.lang.IllegalArgumentException:无法添加指向已存在类型的\u父字段,该类型还不是父类型”。我不确定这是因为版本升级还是b/c,我从一个全新的Elasticsearch服务器安装开始。

    人为的例子显示了我所看到的:

    // UserSearchResult.java
    @Document(indexName = "hr_index", type = "user")
    public class UserSearchResult implements Serializable {
        ...
        @Field(type=FieldType.keyword)
        @Parent(type="department")
        private String departmentCode;
        ...
    }
    
    // DepartmentSearchResult.java
    @Document(indexName = "hr_index", type = "department")
    public class DepartmentSearchResult implements Serializable {
        ...
    }
    

    当我启动我的应用程序时,我得到了这个异常。如果我检查ElasticSearch服务器,我会看到“hr_索引”索引和“部门”映射,但不会创建“用户”映射。

    如果我理解这个错误,那是因为“部门”正在创建,然后当Spring尝试创建“用户”并将“部门”作为其父级时,情况就不一样了,因为部门在创建时之前没有标记为父级。

    1. 有没有办法(通过注释?)当以某种方式创建DepartmentSearchResult时,是否将其表示为父级?

    2. 或者,是否可以向Spring Data Elasticsearch提供一个提示,说明它应该以什么顺序创建索引/映射?我看到了一些其他帖子( Spring Data Elasticsearch Parent/Child Document Repositories / Test execution error )但禁用自动创建,然后自己手动创建(作为Spring代码库的一部分或应用程序的外部)对我来说似乎有点“非Spring-y”?

    3. 或者,我是否应该采取其他方法?

    (这是一个正在工作的Spring应用程序,它一直在使用Spring 4.2.1和Spring Data Release Train Gosling,我正试图升级到使用Spring 5.0.0和Spring Data Release Train Kay。作为其中的一部分,我从一个新的Elasticsearch安装开始,因此我不确定这个错误是来自升级还是仅仅是b/c安装是干净的)。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Nikita Klimov    7 年前

    在SD-ES中,目前与亲子关系相关的问题非常不发达。 问题很可能是由于您使用的是Elasticsearch的干净安装。在更新之前,问题没有出现,因为已经创建了映射。对于解决方案,可以使用elasticsearchTemplate和ApplicationListener,elasticsearchTemplate是SD ES的一部分。这很简单。只需3步。

    在ES中删除索引(只需要一次):

    curl -XDELETE [ES_IP]:9200/hr_index
    

    告诉SD ES不要自动创建索引和映射

    // UserSearchResult.java
    @Document(indexName = "hr_index", type = "user", createIndex = false)
    public class UserSearchResult implements Serializable {
        ...
        @Field(type=FieldType.keyword)
        @Parent(type="department")
        private String departmentCode;
        ...
    }
    
    // DepartmentSearchResult.java
    @Document(indexName = "hr_index", type = "department", createIndex = false)
    public class DepartmentSearchResult implements Serializable {
        ...
    }
    

    添加应用程序侦听器:

    @Component
    public class ApplicationStartupListener implements ApplicationListener<ContextRefreshedEvent> {
    
        @Autowired
        private ElasticsearchTemplate elasticsearchTemplate;
    
        //Mapping for child must be created only if mapping for parents doesn't exist
        @Override
        public void onApplicationEvent(ContextRefreshedEvent event) {
            elasticsearchTemplate.createIndex(DepartmentSearchResult.class);
            try {
                elasticsearchTemplate.getMapping(DepartmentSearchResult.class);
            } catch (ElasticsearchException e) {
                elasticsearchTemplate.putMapping(UserSearchResult.class);
                elasticsearchTemplate.putMapping(DepartmentSearchResult.class);
            }
        }
    }
    

    附笔。 值得注意的是,随着ES 5.6的发布, a process for removing types began . 这不可避免地需要消除亲子关系。在SD ES的下一个版本中,我们将提供使用连接的机会。处理亲子关系不太可能得到改善