如何在应用程序启动时正确处理 "can't add a _parent field that points to an already existing type, that isn't already a parent"

How to correctly address "can't add a _parent field that points to an already existing type, that isn't already a parent" on app startup

我 运行 遇到了一个问题,我的 Elasticsearch 文档索引创建在 "java.lang.IllegalArgumentException: can't add a _parent field that points to an already existing type, that isn't already a parent" 启动时失败。我不确定这是由于版本升级还是 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_index" 索引和 "department" 映射,但未创建 "user" 映射。

如果我理解错误,那是因为 "department" 正在创建,然后当 Spring 尝试创建 "user" 并以 "department" 作为其父级时,它没有不像那样,因为部门在创建时之前没有被标记为父部门。

  1. 是否有某种方式(通过注释?)在以某种方式创建时将 DepartmentSearchResult 表示为父级?

  2. 或者,是否可以提示 Spring Data Elasticsearch 应该以什么顺序创建 indices/mappings?我看过其他一些帖子 (Spring Data Elasticsearch Parent/Child Document Repositories / Test execution error),但禁用自动创建然后自己手动创建它(作为我的 Spring 代码库的一部分或在应用程序外部)似乎有点 "un-Spring-y"我?

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

(这是一个有效的 Spring 应用程序,一直在使用 Spring 4.2.1 和 Spring Data Release Train Gosling,我正在尝试升级以使用 Spring 5.0.0 和 Spring 数据发布 Train Kay。作为其中的一部分,我从全新的 Elasticsearch 安装开始,所以我不确定这个错误是来自升级还是只是 b/c 安装是干净的)。

在SD ES中,目前有关亲子关系的问题确实很差。 该问题很可能是由于您使用的是全新安装的 Elasticsearch。更新之前没有出现这个问题,因为映射已经创建好了。对于解决方案,您可以使用 elasticsearchTemplate(它是 SD ES 的一部分)和 ApplicationListener。这很简单。只需 3 个步骤。

ES中的drop index(只需要一次):

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 {
    ...
}

添加 ApplicationListener:

@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);
        }
    }
}

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