springboot整合ElasticSeach-RestHighLevelClient
本文基于jdk1.8,springboot-2.1.4.RELEASE
1. pom.xml
版本号要保持一致,避免莫名报错
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.3.1</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.3.1</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.3.1</version>
</dependency>
2.application.properties
#elasticseach配置
cw.es-ip=10.128.129.214
cw.es-port=11206
cw.es-protocol=http
如果项目中依赖了spring-boot-actuator包,则需要下面配置,否则报连接localhost:9200失败
es.facedbface.index.mappingTm=false
es.facedbface.index.numberOfShards=5
es.facedbface.index.numberOfReplicas=1
es.facedbface.index.refreshInterval=500ms
spring.elasticsearch.nodes=10.1.1.240:9200
spring.elasticsearch.client.connect-timeout=1000
spring.elasticsearch.client.connection-request-timeout=500
spring.elasticsearch.client.socket-timeout=20000
spring.elasticsearch.client.max-conn-total=100
spring.elasticsearch.client.max-conn-per-route=100
spring.elasticsearch.pool.min-idle=10
spring.elasticsearch.pool.max-idle=20
spring.elasticsearch.pool.max-active=30
#关闭elasticsearch 的健康检查
management.health.elasticsearch.enabled=false
3.配置RestHighLevelClient
编写配置,给容器中注入RestHighLevelClient对象
import org.apache.http.HttpHost;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 1、导入依赖
* 2、编写配置,给容器中注入RestHighLevelClient对象
* 3、操作Es
*/
@Configuration
public class ElasticSearchConfig {
@Value("${cw.es-ip}")
private String esIp;
@Value("${cw.es-port}")
private int esPort;
@Value("${cw.es-protocol}")
private String esProtocol;
public static final RequestOptions COMMON_OPTIONS;
static {
RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
// builder.addHeader("Authorization","Bearer" + TOKEN);
// builder.setHttpAsyncResponseConsumerFactory(
// new HttpAsyncResponseConsumerFactory.
// HeapBufferedResponseConsumerFactory(30 * 1024 * 1024 * 1024)
// );
COMMON_OPTIONS = builder.build();
}
@Bean
public RestHighLevelClient esRestClient() {
RestClientBuilder builder = null;
final String[] ips = esIp.split(",");
final HttpHost[] httpHosts = new HttpHost[ips.length];
for(int i=0;i<ips.length;i++){
httpHosts[i] = new HttpHost(ips[i], esPort, esProtocol);
}
builder = RestClient.builder(httpHosts);
RestHighLevelClient restHighLevelClient = new RestHighLevelClient(builder);
return restHighLevelClient;
}
}
4.常用操作
参考官方文档https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.x/java-rest-high-search.html
public class DemoService{
@Autowired
RestHighLevelClient restHighLevelClient;
/**
* 新建ES索引
*
* @param indexName
* @return
* @throws IOException
*/
public CreateIndexResponse createIndex(String indexName) throws IOException {
log.info("开始新建ES索引={}", indexName);
CreateIndexRequest request = new CreateIndexRequest(indexName);
request.settings(Settings.builder()
.put("index.number_of_shards", 5)
.put("index.number_of_replicas", 1)
);
request.alias(
new Alias(indexName + "_alias")
);
CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
if (createIndexResponse.isAcknowledged()) {
log.info("新建索引{}成功", indexName);
}
log.info("结束新建ES索引={}", indexName);
return createIndexResponse;
}
/**
* 删除ES索引
*
* @param indexName
* @return
* @throws IOException
*/
public AcknowledgedResponse deleteIndex(String indexName) throws IOException {
log.info("开始删除ES索引={}", indexName);
DeleteIndexRequest request = new DeleteIndexRequest(indexName);
final AcknowledgedResponse res = restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
if (res.isAcknowledged()) {
log.info("删除索引{}成功", indexName);
}
log.info("结束删除ES索引={}", indexName);
return res;
}
/**
* 复制ES索引
*
* @param sourceIndex
* @param destIndex
* @return
* @throws IOException
*/
public BulkByScrollResponse reIndex(String sourceIndex, String destIndex) throws IOException {
log.info("开始复制ES索引,从{}到{}", sourceIndex, destIndex);
ReindexRequest request = new ReindexRequest();
request.setSourceIndices(sourceIndex);
request.setDestIndex(destIndex);
request.setSourceBatchSize(5000);
request.setDestOpType("create");
request.setConflicts("proceed");
final BulkByScrollResponse reindex = restHighLevelClient.reindex(request, RequestOptions.DEFAULT);
if (reindex.isTimedOut()) {
log.info("复制索引{}到索引{}成功", sourceIndex, destIndex);
}
log.info("结束复制ES索引,从{}到{}", sourceIndex, destIndex);
return reindex;
}
}
reIndex操作可以实现将一个索引的数据复制到另一个索引,甚至不通集群间复制。要求源索引和目标索引必须存在。
实际遇到的使用场景:pg里有300万数据,es中的数据是pg数据的缩影用于快速查询,入库时先入es后入pg,但pg表中设置了某个字段唯一,导致大量数据成功存入es后再存pg失败。这样es中产生了500万多余数据。
此处可以使用reIndex解决:先新建一个原索引的副本,将数据全部复制进去作为备份。然后新建一个原索引同名索引,将pg里的所有数据导入进去。
5.复制索引
方式1: 使用_reindex
http://ip:port/
_reindex post
{
"source": {
"index": "library-facedbface"
},
"dest": {
"index": "library-facedbface-002",
"op_type": "create"
}
}
该api会将原索引的数据全部复制到新索引。要求新索引必须在操作之前存在。数据量大的话速度较慢。
方式2:使用_clone
POST /my_source_index/_clone/my_target_index
{
"settings": {
"index.number_of_shards": 5
},
"aliases": {
"my_search_indices": {}
}
}
该api是es7.4以后才提供的。它是文件级别的操作,速度较快。
只有满足以下要求的索引才能被克隆:
- 原索引状态必须为只读。
- 目标索引必须不存在。
- 源索引必须具有与目标索引相同数量的主碎片。
- 处理克隆过程的节点必须具有足够的可用磁盘空间,以容纳现有索引的第二个副本。