我正在尝试使用最新版本的Elastic Search库,该库已在Maven仓库中提供。
<dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>7.0.0</version> </dependency>
但不确定如何在导入了6.5的Spring Boot中使用第七版。我的Maven依赖项:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency>
更新
Spring Boot 2.3集成了spring-data-elasticsearch 4,因此将立即支持ElasticSearch7.x。它将很快发布,但是您已经可以尝试:
plugins { id 'org.springframework.boot' version '2.3.0.RC1' id 'io.spring.dependency-management' version '1.0.9.RELEASE' }
我已经对其进行了积极的测试,并且我所有的测试场景都通过了,所以我绝对会推荐这种方式。对于某些出于某些原因无法升级到2.3的人们,我将在下面保留答案。
OLD WORKAROUND (先前版本的原始答案)
我们真的不知道什么时候发布 Spring Data Elastic Search 4.x ,所以我发布了整合当前 Spring Data Elastic Search 4.x 和稳定的 Spring Boot 2.1.7的方式 。如果您想使用Spring Repositories和最新的Elastic Search,它可能是您的临时解决方法。
1)在依赖项中强制使用最新的elasticsearch客户端(在我的情况下: 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)禁用elasticsearch自动配置和运行状况检查组件,因为它们变得不兼容(您稍后可能要实施自己的运行状况检查)。
@SpringBootApplication(exclude = {ElasticsearchAutoConfiguration.class, ElasticSearchRestHealthIndicatorAutoConfiguration.class}) @EnableElasticsearchRepositories public class SpringBootApp { public static void main(String[] args) { SpringApplication.run(SpringBootApp.class, args); } }
3)当我们禁用自动配置时,我们需要初始化ElasticsearchRestTemplate自己。我们还需要这样做以提供自定义,MappingElasticsearchConverter以避免类不兼容。
ElasticsearchRestTemplate
MappingElasticsearchConverter
/** * 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:
/** * 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); } }