0.引言
在springboot整合spring data elasticsearch项目中,当索引数量较多,mapping结构较为复杂时,我们常常希望启动项目时能够自动创建索引及mapping,这样就不用再到各个环境中创建索引了
所以今天咱们就来看看如何自动创建索引
1. 思路
我们已经在实体类中声明了索引数据结构了,只需要识别有@Document
注解的实体类,然后调用ElasticsearchRestTemplate
的createIndex
和putMapping
方法即可创建索引及mapping
2. 实操
1、因为要调用ElasticsearchRestTemplate,所以要提前声明其bean,这个我们在之前的文章中已经讲解过,有需要的同学可以参考之前的文章
从零搭建springboot+spring data elasticsearch3.x环境
2、首先要获取所有添加@Document
注解的实体类,我们需要通过Reflections
类来实现
添加依赖
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.11</version>
</dependency>
获取方法如下,其中com.example.estest.entity
是实体类的包名
Reflections f = new Reflections("com.example.estest.entity");
Set<Class<?>> classSet = f.getTypesAnnotatedWith(Document.class);
3、创建项目启动后调用的配置类
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.reflections.Reflections;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import java.util.Set;
/**
* @author whx
* @date 2022/7/2
*/
@Configuration
@Slf4j
@AllArgsConstructor
public class ElasticCreateIndexStartUp implements ApplicationListener<ContextRefreshedEvent> {
private final ElasticsearchRestTemplate restTemplate;
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent){
log.info("[elastic]索引初始化...");
Reflections f = new Reflections("com.example.estest.entity");
Set<Class<?>> classSet = f.getTypesAnnotatedWith(Document.class);
for (Class<?> clazz : classSet) {
if(!restTemplate.indexExists(clazz)){
restTemplate.createIndex(clazz);
restTemplate.putMapping(clazz);
log.info(String.format("[elastic]索引%s数据结构创建成功",clazz.getSimpleName()));
}
}
log.info("[elastic]索引初始化完毕");
}
}
需要注意以上操作基于spring-data-elasticsearch3.2.12.RELEASE
,spring-data-elasticsearch4.2.x
版本的配置如下
1、ElasticsearchRestTemplate bean的声明
@Configuration
@EnableElasticsearchRepositories(basePackages = "com.example.estest")
public class ElasticRestClientConfig extends AbstractElasticsearchConfiguration {
@Value("${spring.elasticsearch.rest.uris}")
private String url;
@Value("${spring.elasticsearch.rest.username}")
private String username;
@Value("${spring.elasticsearch.rest.password}")
private String password;
@Override
@Bean
public RestHighLevelClient elasticsearchClient() {
url = url.replace("http://","");
String[] urlArr = url.split(",");
HttpHost[] httpPostArr = new HttpHost[urlArr.length];
for (int i = 0; i < urlArr.length; i++) {
HttpHost httpHost = new HttpHost(urlArr[i].split(":")[0].trim(),
Integer.parseInt(urlArr[i].split(":")[1].trim()), "http");
httpPostArr[i] = httpHost;
}
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,new UsernamePasswordCredentials(username,password));
RestClientBuilder builder = RestClient.builder(httpPostArr)
// 异步httpclient配置
.setHttpClientConfigCallback(httpClientBuilder -> {
// 账号密码登录
httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
// httpclient连接数配置
httpClientBuilder.setMaxConnTotal(30);
httpClientBuilder.setMaxConnPerRoute(10);
// httpclient保活策略
httpClientBuilder.setKeepAliveStrategy(((response, context) -> Duration.ofMinutes(5).toMillis()));
return httpClientBuilder;
});
return new RestHighLevelClient(builder);
}
@Bean
public ElasticsearchRestTemplate elasticsearchRestTemplate(RestHighLevelClient elasticsearchClient,ElasticsearchConverter elasticsearchConverter){
return new ElasticsearchRestTemplate(elasticsearchClient,elasticsearchConverter);
}
}
2、索引创建类
@Configuration
@Slf4j
@AllArgsConstructor
public class ElasticCreateIndexStartUp implements ApplicationListener<ContextRefreshedEvent> {
private final ElasticsearchRestTemplate restTemplate;
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent){
log.info("[elastic]索引初始化...");
Reflections f = new Reflections("com.example.estest.entity");
Set<Class<?>> classSet = f.getTypesAnnotatedWith(Document.class);
for (Class<?> clazz : classSet) {
IndexOperations indexOperations = restTemplate.indexOps(clazz);
if(!indexOperations.exists()){
indexOperations.create();
indexOperations.putMapping();
log.info(String.format("[elastic]索引%s数据结构创建成功",clazz.getSimpleName()));
}
}
log.info("[elastic]索引初始化完毕");
}
}