如何将ElasticSearch 7.0版本与Spring Boot集成? [英] How to integrate ElasticSearch 7.0 version with Spring Boot?

查看:87
本文介绍了如何将ElasticSearch 7.0版本与Spring Boot集成?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用最新版本的Elastic Search库,该库已在maven仓库中提供.

I'm trying to use the latest version of Elastic Search library which is already available in the maven repos.

<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>7.0.0</version>
</dependency>

但不确定如何在导入了6.5的Spring Boot中使用第七版. 我的Maven依赖项:

But not sure how can I use the 7th version with Spring Boot which imports 6.5. My maven dependency:

  <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
  </dependency>

推荐答案

更新

Spring Boot 2.3集成了spring-data-elasticsearch 4,因此它将开箱即用地支持ElasticSearch7.x.它将很快发布,但您已经可以尝试:

Spring Boot 2.3 is integrating spring-data-elasticsearch 4 so it will support ElasticSearch 7.x out of the box. It will be released soon but you can already try it:

plugins {
  id 'org.springframework.boot' version '2.3.0.RC1'
  id 'io.spring.dependency-management' version '1.0.9.RELEASE'
}

我已经对其进行了积极的测试,并且我的所有测试场景都通过了,所以我绝对会推荐这种方式.对于某些出于某些原因无法升级到2.3的人们,我将在下面保留答案.

I have tested it positively and all of my test scenarios are passing so I would definitely recommend this way. I will keep the answer below for people that for some reasons can't upgrade to 2.3.

旧解决方法(以前的版本为原始答案)

OLD WORKAROUND (previous versions original answer)

由于我们真的不知道何时发布 Spring Data Elastic Search 4.x ,我发布了整合当前 Spring的方式数据弹性搜索 4.x 和稳定的 Spring Boot 2.1.7 .如果您想使用Spring Repositories和最新的Elastic Search,它可能是您的临时解决方法.

As we don`t really know when Spring Data Elastic Search 4.x is going to be released I am posting my way of integrating the current Spring Data Elastic Search 4.x and stable Spring Boot 2.1.7. It might work as a temporary workaround for you if you want to work with the Spring Repositories and the newest Elastic Search.

1)在您的依赖项中强制使用最新的弹性搜索客户端(在我的情况下为: build.gradle )

1) Force newest elastic search client in your dependencies (in my case: build.gradle)

dependencies {
    //Force spring-data to use the newest elastic-search client
    //this should removed as soon as spring-data-elasticsearch:4.0.0 is released!
    implementation('org.springframework.data:spring-data-elasticsearch:4.0.0.BUILD-SNAPSHOT') {
        exclude group: 'org.elasticsearch'
        exclude group: 'org.elasticsearch.plugin'
        exclude group: 'org.elasticsearch.client'
    }

    implementation('org.elasticsearch:elasticsearch:7.3.0') { force = true }
    implementation('org.elasticsearch.client:elasticsearch-rest-high-level-client:7.3.0') { force = true }
    implementation('org.elasticsearch.client:elasticsearch-rest-client:7.3.0') { force = true }
}

2)禁用弹性搜索自动配置和运行状况检查组件,因为它们变得不兼容(您以后可能要实施自己的运行状况检查).

2) Disable the Elastic Search auto configuration and health check components as they become incompatible (you may later want to implement your own health check).

@SpringBootApplication(exclude = {ElasticsearchAutoConfiguration.class, ElasticSearchRestHealthIndicatorAutoConfiguration.class})
@EnableElasticsearchRepositories
public class SpringBootApp {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootApp.class, args);
    }

}

3)禁用自动配置后,我们需要自行初始化ElasticsearchRestTemplate.我们还需要提供自定义MappingElasticsearchConverter来避免类不兼容.

3) As we disabled the auto configuration we need to initialize the ElasticsearchRestTemplate ourselves. We also need to do it to provide the custom MappingElasticsearchConverter to avoid class incompatibilities.

/**
 * Manual configuration to support the newest ElasticSearch that is currently not supported by {@link org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration}.
 *
 * @author aleksanderlech
 */
@Configuration
@EnableConfigurationProperties(ElasticsearchProperties.class)
public class ElasticSearchConfiguration {

    @Primary
    @Bean
    public ElasticsearchRestTemplate elasticsearchTemplate(ElasticsearchProperties configuration) {
        var nodes =  Stream.of(configuration.getClusterNodes().split(",")).map(HttpHost::create).toArray(HttpHost[]::new);
        var client = new RestHighLevelClient(RestClient.builder(nodes));
        var converter = new CustomElasticSearchConverter(new SimpleElasticsearchMappingContext(), createConversionService());
        return new ElasticsearchRestTemplate(client, converter, new DefaultResultMapper(converter));
    }

    private DefaultConversionService createConversionService() {
        var conversionService = new DefaultConversionService();
        conversionService.addConverter(new StringToLocalDateConverter());
        return conversionService;
    }
}

CustomElasticSearchConverter:

CustomElasticSearchConverter:

/**
 * Custom version of {@link MappingElasticsearchConverter} to support newest Spring Data Elasticsearch integration that supports ElasticSearch 7. Remove when Spring Data Elasticsearch 4.x is released.
 */
class CustomElasticSearchConverter extends MappingElasticsearchConverter {

    private CustomConversions conversions = new ElasticsearchCustomConversions(Collections.emptyList());

    CustomElasticSearchConverter(MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext) {
        super(mappingContext);
        setConversions(conversions);
    }

    CustomElasticSearchConverter(MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext, GenericConversionService conversionService) {
        super(mappingContext, conversionService);
        setConversions(conversions);
    }

    @Override
    protected <R> R readValue(@Nullable Object source, ElasticsearchPersistentProperty property,
                              TypeInformation<R> targetType) {

        if (source == null) {
            return null;
        }

        if (source instanceof List) {
            return readCollectionValue((List) source, property, targetType);
        }

        return super.readValue(source, property, targetType);
    }

    private Object readSimpleValue(@Nullable Object value, TypeInformation<?> targetType) {

        Class<?> target = targetType.getType();

        if (value == null || target == null || ClassUtils.isAssignableValue(target, value)) {
            return value;
        }

        if (conversions.hasCustomReadTarget(value.getClass(), target)) {
            return getConversionService().convert(value, target);
        }

        if (Enum.class.isAssignableFrom(target)) {
            return Enum.valueOf((Class<Enum>) target, value.toString());
        }

        return getConversionService().convert(value, target);
    }


    private <R> R readCollectionValue(@Nullable List<?> source, ElasticsearchPersistentProperty property,
                                      TypeInformation<R> targetType) {

        if (source == null) {
            return null;
        }

        Collection<Object> target = createCollectionForValue(targetType, source.size());

        for (Object value : source) {

            if (isSimpleType(value)) {
                target.add(
                        readSimpleValue(value, targetType.getComponentType() != null ? targetType.getComponentType() : targetType));
            } else {

                if (value instanceof List) {
                    target.add(readValue(value, property, property.getTypeInformation().getActualType()));
                } else {
                    target.add(readEntity(computeGenericValueTypeForRead(property, value), (Map) value));
                }
            }
        }

        return (R) target;
    }

    private Collection<Object> createCollectionForValue(TypeInformation<?> collectionTypeInformation, int size) {

        Class<?> collectionType = collectionTypeInformation.isCollectionLike()//
                ? collectionTypeInformation.getType() //
                : List.class;

        TypeInformation<?> componentType = collectionTypeInformation.getComponentType() != null //
                ? collectionTypeInformation.getComponentType() //
                : ClassTypeInformation.OBJECT;

        return collectionTypeInformation.getType().isArray() //
                ? new ArrayList<>(size) //
                : CollectionFactory.createCollection(collectionType, componentType.getType(), size);
    }

    private ElasticsearchPersistentEntity<?> computeGenericValueTypeForRead(ElasticsearchPersistentProperty property,
                                                                            Object value) {

        return ClassTypeInformation.OBJECT.equals(property.getTypeInformation().getActualType())
                ? getMappingContext().getRequiredPersistentEntity(value.getClass())
                : getMappingContext().getRequiredPersistentEntity(property.getTypeInformation().getActualType());
    }

    private boolean isSimpleType(Object value) {
        return isSimpleType(value.getClass());
    }

    private boolean isSimpleType(Class<?> type) {
        return conversions.isSimpleType(type);
    }

}

这篇关于如何将ElasticSearch 7.0版本与Spring Boot集成?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆