四种方式
操作es的主要有四种方式:
第一种 :spring date es ,这种方式简单,多用于一些简单业务,但因为方法都帮你封装好了,灵活度不高!(复杂业务不推荐)
第二种 :transportClient ,这种方式,官方已经明确表示在ES 7.0版本中将弃用TransportClient客户端,且在8.0版本中完全移除它
第三种 :REST Client 这种方式是基于http 与 es 通信,方便(官网推荐),主要有restHighLevelClient 和restlowLevelClient俩版本,这里也是我是选用的方式.
第四种:Http restful api接口调用,elaticsearch-head常用方式
依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.yidu</groupId>
<artifactId>yangguangetl</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>yangguangetl</name>
<description>ETL project to transfer data from mysql to es and mysql</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.elasticsearch/elasticsearch -->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>6.8.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.61</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.elasticsearch.client/elasticsearch-rest-high-level-client -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.8.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.elasticsearch.client/elasticsearch-rest-client -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>6.8.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.54</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties 配置
#集群用","连接
elasticSearch.hostlist=127.0.0.1:9200
elasticSearch.client.connectNum=10
elasticSearch.client.connectPerRoute=50
配置REST Client
package com.mqm501.es;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
/**
* Project: sunshineetl Package: com.mqm501.es
* <p>Create Time: 2019年10月12日 17:13 </p>
* <p>@author: qingmei.meng </p>
* <p>Description: </p>
**/
@Configuration
@ComponentScan(basePackageClasses=ESClientSpringFactory.class)
public class ElasticsearchConfig {
@Value("${elasticSearch.client.connectNum}")
private Integer connectNum;
@Value("${elasticSearch.client.connectPerRoute}")
private Integer connectPerRoute;
@Value("${elasticSearch.hostlist}")
private String hostlist;
@Bean
public HttpHost[] httpHost(){
//解析hostlist配置信息
String[] split = hostlist.split(",");
//创建HttpHost数组,其中存放es主机和端口的配置信息
HttpHost[] httpHostArray = new HttpHost[split.length];
for(int i=0;i<split.length;i++){
String item = split[i];
httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")[1]), "http");
}
return httpHostArray;
}
@Bean(initMethod="init",destroyMethod="close")
public ESClientSpringFactory getFactory(){
return ESClientSpringFactory.
build(httpHost(), connectNum, connectPerRoute);
}
@Bean
@Scope("singleton")
public RestClient getRestClient(){
return getFactory().getClient();
}
@Bean(name = "restHighLevelClient")
@Scope("singleton")
public RestHighLevelClient getRHLClient(){
return getFactory().getRhlClient();
}
}
package com.mqm501.es;
import java.io.IOException;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
/**
* Project: sunshineetl Package: com.mqm501.es
* <p>Create Time: 2019年10月12日 17:15 </p>
* <p>@author: qingmei.meng </p>
* <p>Description: </p>
**/
public class ESClientSpringFactory {
public static int CONNECT_TIMEOUT_MILLIS = 1000;
public static int SOCKET_TIMEOUT_MILLIS = 30000;
public static int CONNECTION_REQUEST_TIMEOUT_MILLIS = 500;
public static int MAX_CONN_PER_ROUTE = 10;
public static int MAX_CONN_TOTAL = 30;
private static HttpHost[] HTTP_HOST;
private RestClientBuilder builder;
private RestClient restClient;
private RestHighLevelClient restHighLevelClient;
private static ESClientSpringFactory esClientSpringFactory = new ESClientSpringFactory();
private ESClientSpringFactory(){}
public static ESClientSpringFactory build(HttpHost[] httpHostArray,
Integer maxConnectNum, Integer maxConnectPerRoute){
HTTP_HOST = httpHostArray;
MAX_CONN_TOTAL = maxConnectNum;
MAX_CONN_PER_ROUTE = maxConnectPerRoute;
return esClientSpringFactory;
}
public static ESClientSpringFactory build(HttpHost[] httpHostArray,Integer connectTimeOut, Integer socketTimeOut,
Integer connectionRequestTime,Integer maxConnectNum, Integer maxConnectPerRoute){
HTTP_HOST = httpHostArray;
CONNECT_TIMEOUT_MILLIS = connectTimeOut;
SOCKET_TIMEOUT_MILLIS = socketTimeOut;
CONNECTION_REQUEST_TIMEOUT_MILLIS = connectionRequestTime;
MAX_CONN_TOTAL = maxConnectNum;
MAX_CONN_PER_ROUTE = maxConnectPerRoute;
return esClientSpringFactory;
}
public void init(){
builder = RestClient.builder(HTTP_HOST);
setConnectTimeOutConfig();
setMutiConnectConfig();
restClient = builder.build();
restHighLevelClient = new RestHighLevelClient(builder);
System.out.println("init factory");
}
// 配置连接时间延时
public void setConnectTimeOutConfig(){
builder.setRequestConfigCallback(requestConfigBuilder -> {
requestConfigBuilder.setConnectTimeout(CONNECT_TIMEOUT_MILLIS);
requestConfigBuilder.setSocketTimeout(SOCKET_TIMEOUT_MILLIS);
requestConfigBuilder.setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT_MILLIS);
return requestConfigBuilder;
});
}
// 使用异步httpclient时设置并发连接数
public void setMutiConnectConfig(){
builder.setHttpClientConfigCallback(httpClientBuilder -> {
httpClientBuilder.setMaxConnTotal(MAX_CONN_TOTAL);
httpClientBuilder.setMaxConnPerRoute(MAX_CONN_PER_ROUTE);
return httpClientBuilder;
});
}
public RestClient getClient(){
return restClient;
}
public RestHighLevelClient getRhlClient(){
return restHighLevelClient;
}
public void close() {
if (restClient != null) {
try {
restClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("close client");
}
}
配置esUtils
package com.mqm501.es;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mqm501.es.SpringBeanUtil;
import com.mqm501.es.entity.es.ESCustomer;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.IndicesClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexResponse;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
/**
* Project: sunshineetl Package: mqm501.es
* <p>Create Time: 2019年10月12日 17:19 </p>
* <p>@author: qingmei.meng </p>
* <p>Description: </p>
**/
public class EsUtils {
private static RestHighLevelClient client;
public static RestHighLevelClient getInstance() {
if (client == null) {
synchronized (RestHighLevelClient.class) {
if (client == null) {
client = (RestHighLevelClient) SpringBeanUtil.getBean("restHighLevelClient");
System.out.println(client);
}
}
}
return client;
}
public static void main(String[] args) {
getInstance();
}
/**
* 创建索引
*
* @param index 索引名称
* @param type 类型名称,可传入多个type逗号分隔
* @param arg1 分片数
* @param arg2 副本数
* @param source 需要设置的映射(配置是否分词,是否索引等)
* @return boolean
*/
public static boolean addIndex(String index, String type, int arg1, int arg2, String source) {
CreateIndexRequest createIndexRequest = new CreateIndexRequest(index);
//设置索引参数
createIndexRequest.settings(
Settings.builder().put("number_of_shards", arg1).put("number_of_replicas", arg2));
//操作索引的客户端
createIndexRequest.mapping(type, source, XContentType.JSON);
IndicesClient indices = getInstance().indices();
//执行创建
CreateIndexResponse createIndexResponse = null;
try {
indices.create(createIndexRequest);
} catch (IOException e) {
e.printStackTrace();
}
//得到响应
return true;
}
/**
* 判断索引是否存在
* @param index
* @return
* @throws IOException
*/
public static boolean existsIndex(String index) throws IOException {
GetIndexRequest request = new GetIndexRequest(index);
//request.indices(index);
//操作索引的客户端
IndicesClient indices = getInstance().indices();
boolean exists = indices.exists(request, RequestOptions.DEFAULT);
System.out.println("existsIndex: " + exists);
return exists;
}
/**
* 删除索引
*
* @param index 索引名称
* @return boolean
*/
public static boolean delIndex(String index) throws IOException {
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(index);
//操作索引的客户端
IndicesClient indices = getInstance().indices();
//执行删除
AcknowledgedResponse deleteIndexResponse = indices.delete(deleteIndexRequest,RequestOptions.DEFAULT);
//得到响应
return deleteIndexResponse.isAcknowledged();
}
/**
* 添加数据
*
* @param index 索引名称
* @param type 类型
* @param jsonObject json对象(要添加的数据)
* @return boolean
*/
public static boolean addDoc(String index, String type, String id, JSONObject jsonObject) {
//索引请求对象
IndexRequest indexRequest = new IndexRequest(index, type, id);
indexRequest.source(jsonObject);
//索引响应对象
try {
getInstance().index(indexRequest);
} catch (IOException e) {
e.printStackTrace();
}
//获取响应结果
return true;
}
/**
* 修改数据
*
* @param index 索引名称
* @param type 类型
* @param jsonObject json对象(要添加的数据)
* @param id
* @return RestStatus ok
*/
public static boolean updateDoc(String index, String type, JSONObject jsonObject, String id) {
UpdateRequest updateRequest = new UpdateRequest(index, type, id);
updateRequest.doc(jsonObject);
//索引响应对象
UpdateResponse update = null;
try {
getInstance().update(updateRequest);
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
/**
* 获取记录信息
* @param index
* @param type
* @param id
* @throws IOException
*/
public static void getDoc(String index, String type, String id) {
GetIndexRequest getRequest = new GetIndexRequest(index, type, id.toString());
//操作索引的客户端
IndicesClient indices = getInstance().indices();
GetIndexResponse getResponse = null;
try {
getResponse = indices.get(getRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("get: " + JSON.toJSONString(getResponse));
}
/**
* 删除数据
*
* @param index 索引名称
* @param type 类型
* @param id 文档id(即某条数据的id)
* @return RestStatus ok
*/
public static boolean deleteDoc(String index, String type, String id) {
DeleteRequest deleteRequest = new DeleteRequest(index, type, id);
//索引响应对象
try {
getInstance().delete(deleteRequest);
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
/**
* 使用分词查询
*
* @param index 索引名称
* @param type 类型
* @param fields 需要显示的字段,逗号分隔(缺省为全部字段)
* @param query 查询条件
* @param sortField 排序字段(倒序)
* @return List<Map < String, Object>>
*/
public static List<Map<String, Object>> search(String index, String type, String fields, QueryBuilder query, String sortField, String highlightField) {
//搜索对象
SearchRequest searchRequest = new SearchRequest(index);
//设置类型
searchRequest.types(type);
//搜索源对象构建
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//搜索条件
searchSourceBuilder.query(query);
//设置按字段排序
if (StringUtils.isNotEmpty(sortField)) {
searchSourceBuilder.sort(sortField, SortOrder.DESC);
}
//过滤字段
if (StringUtils.isNotEmpty(fields)) {
searchSourceBuilder.fetchSource(fields.split(","), null);
}
return trySearch(searchRequest, searchSourceBuilder, highlightField);
}
/**
* 使用分词查询 并分页
*
* @param index 索引名称
* @param type 类型
* @param fields 需要显示的字段,逗号分隔(缺省为全部字段)
* @param query 查询条件
* @param sortField 排序字段
* @param highlightField 高亮字段
* @return List<Map < String, Object>>
*/
public static List<Map<String, Object>> searchPage(
String index, String type, String fields, QueryBuilder query,
String sortField, int size, int page, String highlightField) {
//搜索对象
SearchRequest searchRequest = new SearchRequest(index);
//设置类型
searchRequest.types(type);
//搜索源对象构建0
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//计算起始下标
int from = (page - 1) * size;
searchSourceBuilder.from(from);//起始下标,从0开始
searchSourceBuilder.size(size);//每页记录数
//设置搜索条件
searchSourceBuilder.query(query);
//过滤字段
if (StringUtils.isNotEmpty(fields)) {
searchSourceBuilder.fetchSource(fields.split(","), null);
}
//设置按字段排序
if (StringUtils.isNotEmpty(sortField)) {
searchSourceBuilder.sort(sortField, SortOrder.DESC);
}
return trySearch(searchRequest, searchSourceBuilder, highlightField);
}
/**
* 进行搜索
*
* @param searchRequest
* @param searchSourceBuilder
*/
public static List<Map<String, Object>> trySearch(SearchRequest searchRequest, SearchSourceBuilder searchSourceBuilder, String highlightField) {
//设置搜索源
searchRequest.source(searchSourceBuilder);
//设置高亮
if (StringUtils.isNotEmpty(highlightField)) {
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.preTags("<highlight>");
highlightBuilder.postTags("</highlight>");
highlightBuilder.fields().add(new HighlightBuilder.Field(highlightField));
searchSourceBuilder.highlighter(highlightBuilder);
}
//执行搜索
SearchResponse searchResponse = null;
try {
searchResponse = getInstance().search(searchRequest,RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
//搜索匹配结果
SearchHits hits = searchResponse.getHits();
//搜索总记录数
long totalHits = hits.getTotalHits();
System.out.println("搜索总记录数=====" + totalHits);
//匹配度较高的前n的文档
SearchHit[] searchHits = hits.getHits();
List<Map<String, Object>> searchList = new ArrayList<>();
for (SearchHit hit : searchHits) {
//文档id
String id = hit.getId();
//源文档内容
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
//获取源文档需要高亮的字段
String name = (String) sourceAsMap.get(highlightField);
//取出高亮字段
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
if (highlightFields != null) {
//取出name高亮字段
HighlightField nameField = highlightFields.get(highlightField);
if (nameField != null) {
Text[] fragments = nameField.fragments();
StringBuffer stringBuffer = new StringBuffer();
for (Text text : fragments) {
stringBuffer.append(text);
}
name = stringBuffer.toString();
hit.getSourceAsMap().put(highlightField, name);
}
}
searchList.add(hit.getSourceAsMap());
System.out.println(name);
}
return searchList;
}
/**
* 批量操作
*
* @param index 索引名称
* @param type 类型名称,可传入多个type逗号分隔
* @param sourceList json数据列表
* @throws IOException
*/
public static void bulk(String index, String type, List<String> sourceList) throws IOException {
// 批量增加
BulkRequest bulkAddRequest = new BulkRequest();
for (String source : sourceList) {
IndexRequest indexRequest = new IndexRequest(index, type);
indexRequest.source(source, XContentType.JSON);
bulkAddRequest.add(indexRequest);
}
BulkResponse bulkAddResponse = getInstance().bulk(bulkAddRequest, RequestOptions.DEFAULT);
System.out.println("bulkAdd: " + JSON.toJSONString(bulkAddResponse));
if (bulkAddResponse.hasFailures()) {
System.out.println("faliure");
for (BulkItemResponse bulkItemResponse : bulkAddResponse) {
if (bulkItemResponse.isFailed()) {
BulkItemResponse.Failure failure =
bulkItemResponse.getFailure();
}
}
}
for (BulkItemResponse bulkItemResponse : bulkAddResponse) {
DocWriteResponse itemResponse = bulkItemResponse.getResponse();
switch (bulkItemResponse.getOpType()) {
case INDEX:
case CREATE:
IndexResponse indexResponse = (IndexResponse) itemResponse;
break;
case UPDATE:
UpdateResponse updateResponse = (UpdateResponse) itemResponse;
break;
case DELETE:
DeleteResponse deleteResponse = (DeleteResponse) itemResponse;
}
}
//search(INDEX_TEST, TYPE_TEST, "this");
}
/**
* 批量新增操作
*
* @param index 索引名称
* @param type 类型名称,可传入多个type逗号分隔
* @param sourceList json数据列表
* @throws IOException
*/
public static void bulkAdd(String index, String type, List<String> sourceList) throws IOException {
// 批量增加
BulkRequest bulkAddRequest = new BulkRequest();
for (String source : sourceList) {
//生成默认id
//IndexRequest indexRequest = new IndexRequest(index, type);
//指定id值
IndexRequest indexRequest = new IndexRequest(index, type,JSONObject.parseObject(source).getString("id"));
indexRequest.source(source, XContentType.JSON);
bulkAddRequest.add(indexRequest);
}
BulkResponse bulkAddResponse = getInstance().bulk(bulkAddRequest, RequestOptions.DEFAULT);
System.out.println("bulkAdd: " + JSON.toJSONString(bulkAddResponse));
//search(INDEX_TEST, TYPE_TEST, "this");
}
/**
* 批量更新操作
*
* @param index 索引名称
* @param type 类型名称,可传入多个type逗号分隔
* @param sourceList json数据列表
* @throws IOException
*/
public static void bulkUpdate(String index, String type, List<String> sourceList) throws IOException {
// 批量更新
BulkRequest bulkUpdateRequest = new BulkRequest();
for (String source : sourceList) {
UpdateRequest updateRequest = new UpdateRequest(index, type,JSONObject.parseObject(source).getString("id"));
updateRequest.doc(source, XContentType.JSON);
bulkUpdateRequest.add(updateRequest);
}
BulkResponse bulkUpdateResponse = getInstance().bulk(bulkUpdateRequest, RequestOptions.DEFAULT);
System.out.println("bulkUpdate: " + JSON.toJSONString(bulkUpdateResponse));
//search(INDEX_TEST, TYPE_TEST, "updated");
}
/**
* 批量删除操作
*
* @param index 索引名称
* @param type 类型名称,可传入多个type逗号分隔
* @param sourceList json数据列表
* @throws IOException
*/
public static void bulkDel(String index, String type, List<String> sourceList) throws IOException {
// 批量删除
BulkRequest bulkDeleteRequest = new BulkRequest();
for (String source : sourceList) {
//id为es"_id"字段的值
DeleteRequest deleteRequest = new DeleteRequest(index, type, JSONObject.parseObject(source).getString("id"));
//DeleteRequest deleteRequest = new DeleteRequest(index, type, "C-0rum0BT-MF5Km2BxmD");
bulkDeleteRequest.add(deleteRequest);
}
BulkResponse bulkDeleteResponse = getInstance().bulk(bulkDeleteRequest, RequestOptions.DEFAULT);
System.out.println("bulkDelete: " + JSON.toJSONString(bulkDeleteResponse));
}
//TODO 异步批量操作
}