目前主要的使用连接elasticsearch的组件有:transport,jest和官方的java high level rest client三种,这三种的对比如下图:
|
Java high level rest client |
jest |
transport |
版本 |
官方的,每个es版本均有其客户端 |
截止当前2019年,最新版本6.3.2,支持es版本6.3.1,对es高版本是否支持,不确定,可能会有坑 |
Es7.0计划删除该功能,es8.0完全删除,故该方式忽略 |
增删改查 |
支持 |
支持 |
支持 |
bulk |
支持 |
支持 |
支持 |
复杂查询 |
支持范围查询,聚合查询 |
支持范围查询,聚合查询 |
支持 |
查询删除 |
6.4及之前版本不支持,但自身有对rest client封装,可直接与es服务http方式连接实现查询删除(delete_by_query)) |
支持 |
支持 |
|
|
|
|
由于java high level rest client这种方式,网上的资料特别少,我在使用的时候,查阅了很多资料,经实践之后,把如何使用该组件实现增删查(修改类似,此文忽略),跟大家分享下。
使用的组件如下:
Java:1.8
ES版本:6.5.4
java high level rest client版本:6.5.4
Spring boot版本:1.5
直接分享代码,如下
第一步,连接
Pom.xml配置如下:
org.elasticsearch.client
elasticsearch-rest-high-level-client
6.5.4
application.yml配置如下:
esclient:
host: 10.37.147.56
port: 9200
schema: http
connectTimeOut: 1000
socketTimeOut: 30000
connectionRequestTimeOut: 500
maxConnectNum: 100
maxCconnectPerRoute: 10
EsClientSetting.java
@ConfigurationProperties(prefix = "esclient")
public class EsClientSetting {
private String host;
private int port;
private String schema;
private int connectTimeOut;
private int socketTimeOut;
private int connectionRequestTimeOut;
private int maxConnectNum;
private int maxCconnectPerRoute;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getSchema() {
return schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
public int getConnectTimeOut() {
return connectTimeOut;
}
public void setConnectTimeOut(int connectTimeOut) {
this.connectTimeOut = connectTimeOut;
}
public int getSocketTimeOut() {
return socketTimeOut;
}
public void setSocketTimeOut(int socketTimeOut) {
this.socketTimeOut = socketTimeOut;
}
public int getConnectionRequestTimeOut() {
return connectionRequestTimeOut;
}
public void setConnectionRequestTimeOut(int connectionRequestTimeOut) {
this.connectionRequestTimeOut = connectionRequestTimeOut;
}
public int getMaxConnectNum() {
return maxConnectNum;
}
public void setMaxConnectNum(int maxConnectNum) {
this.maxConnectNum = maxConnectNum;
}
public int getMaxCconnectPerRoute() {
return maxCconnectPerRoute;
}
public void setMaxCconnectPerRoute(int maxCconnectPerRoute) {
this.maxCconnectPerRoute = maxCconnectPerRoute;
}
}
配置连接的factory,ESClientFactory.java
public class ESClientFactory {
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 = 100;
private static HttpHost HTTP_HOST;
private RestClientBuilder builder;
private RestClient restClient;
private RestHighLevelClient restHighLevelClient;
private static ESClientFactory eSClientFactory = new ESClientFactory();
private ESClientFactory(){}
public static ESClientFactory build(HttpHost httpHost,
Integer maxConnectNum, Integer maxConnectPerRoute){
HTTP_HOST = httpHost;
MAX_CONN_TOTAL = maxConnectNum;
MAX_CONN_PER_ROUTE = maxConnectPerRoute;
return eSClientFactory;
}
public static ESClientFactory build(HttpHost httpHost,Integer connectTimeOut, Integer socketTimeOut,
Integer connectionRequestTime,Integer maxConnectNum, Integer maxConnectPerRoute){
HTTP_HOST = httpHost;
CONNECT_TIMEOUT_MILLIS = connectTimeOut;
SOCKET_TIMEOUT_MILLIS = socketTimeOut;
CONNECTION_REQUEST_TIMEOUT_MILLIS = connectionRequestTime;
MAX_CONN_TOTAL = maxConnectNum;
MAX_CONN_PER_ROUTE = maxConnectPerRoute;
return eSClientFactory;
}
public void init(){
builder = RestClient.builder(HTTP_HOST);
setConnectTimeOutConfig();
setMutiConnectConfig();
restClient = builder.build();
restHighLevelClient = new RestHighLevelClient(builder);
}
// 配置连接时间延时
public void setConnectTimeOutConfig(){
builder.setRequestConfigCallback(new RequestConfigCallback() {
@Override
public Builder customizeRequestConfig(Builder 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(new HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder 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");
}
}
配置连接的bean,ESConfig.java
@Configuration
@EnableConfigurationProperties(EsClientSetting.class)
@ComponentScan(basePackageClasses=ESClientFactory.class)
public class ESConfig {
private static final Logger logger = LoggerFactory.getLogger(ESConfig.class);
private final EsClientSetting esClientSetting;
public ESConfig(EsClientSetting esClientSetting){
this.esClientSetting = esClientSetting;
}
@Bean
public HttpHost httpHost(){
return new HttpHost(esClientSetting.getHost(),esClientSetting.getPort(),esClientSetting.getSchema());
}
@Bean(initMethod="init",destroyMethod="close")
public ESClientFactory getFactory(){
return ESClientFactory.
build(httpHost(), esClientSetting.getConnectTimeOut(), esClientSetting.getSocketTimeOut(),
esClientSetting.getConnectionRequestTimeOut(), esClientSetting.getMaxConnectNum(),
esClientSetting.getMaxCconnectPerRoute());
}
@Bean
@Scope("singleton")
public RestClient getRestClient(){
return getFactory().getClient();
}
@Bean
@Scope("singleton")
public RestHighLevelClient getRHLClient(){
return getFactory().getRhlClient();
}
}
至此,配置es的连接bean就ok了。
第二步,就是使用了,如下
EsClientServiceImpl.java
@Service
public class EsClientServiceImpl implements EsClientService {
private Logger log = LoggerFactory.getLogger(EsClientServiceImpl.class);
private Gson gson = new Gson();
private final RestHighLevelClient rhlClient;
private RestClient restClient;
public final static String ESTYPE = "_doc";
@Autowired
public EsClientServiceImpl(RestHighLevelClient rhlClient, RestClient restClient) {
this.rhlClient = rhlClient;
this.restClient = restClient;
}
/**
* 测试接口
*/
public void queryByParama(Map params){
// createIndex();
addTest();
// batchAddTest();
// queryTest();
// delete();
deleteByQuery();
}
//创建索引--测试
public void createIndex(){
CreateIndexRequest request = new CreateIndexRequest("demo2");
request.settings(Settings.builder()
.put("index.number_of_shards", 2)
.put("index.number_of_replicas", 0)
);
request.mapping("_doc",
"{\n" +
" \"_doc\": {\n" +
" \"properties\": {\n" +
" \"title\": {\n" +
" \"type\": \"text\"\n" +
" },\n" +
" \"tag\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"publishTime\": {\n" +
" \"type\": \"date\"\n" +
" }\n" +
" }\n" +
" }\n" +
"}",
XContentType.JSON);
try {
rhlClient.indices().create(request, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
}
//新增--测试
public void addTest() {
IndexRequest indexRequest = new IndexRequest("demo2", "_doc");
News news = new News();
news.setTitle("2中国产小型无人机的“对手”来了,俄微型拦截导弹便宜量又多");
news.setTag("军事");
news.setPublishTime("2018-01-24T23:59:30Z");
String source = gson.toJson(news).toString();
indexRequest.source(source, XContentType.JSON);
try {
rhlClient.index(indexRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//批量新增--测试
public void batchAddTest() {
BulkRequest bulkRequest = new BulkRequest();
List requests = generateRequests();
for (IndexRequest indexRequest : requests) {
bulkRequest.add(indexRequest);
}
try {
rhlClient.bulk(bulkRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public List generateRequests(){
List requests = new ArrayList<>();
requests.add(generateNewsRequest("中印边防军于拉达克举行会晤 强调维护边境和平", "军事", "2018-01-27T08:34:00Z"));
requests.add(generateNewsRequest("费德勒收郑泫退赛礼 进决赛战西里奇", "体育", "2018-01-26T14:34:00Z"));
requests.add(generateNewsRequest("欧文否认拿动手术威胁骑士 兴奋全明星联手詹皇", "体育", "2018-01-26T08:34:00Z"));
requests.add(generateNewsRequest("皇马官方通告拉莫斯伊斯科伤情 将缺阵西甲关键战", "体育", "2018-01-26T20:34:00Z"));
return requests;
}
public IndexRequest generateNewsRequest(String title, String tag, String publishTime){
IndexRequest indexRequest = new IndexRequest("demo", "demo");
News news = new News();
news.setTitle(title);
news.setTag(tag);
news.setPublishTime(publishTime);
String source = gson.toJson(news).toString();
indexRequest.source(source, XContentType.JSON);
return indexRequest;
}
//按条件查询--测试
public void queryTest(){
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.from(0);
sourceBuilder.size(10);
sourceBuilder.fetchSource(new String[]{"title"}, new String[]{});
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", "中国");
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("tag", "军事");
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("publishTime");
rangeQueryBuilder.gte("2018-01-23T08:00:00Z");
rangeQueryBuilder.lte("2018-01-26T20:00:00Z");
BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
boolBuilder.must(matchQueryBuilder);
boolBuilder.must(termQueryBuilder);
boolBuilder.must(rangeQueryBuilder);
sourceBuilder.query(boolBuilder);
SearchRequest searchRequest = new SearchRequest("demo2");
searchRequest.types("_doc");
searchRequest.source(sourceBuilder);
try {
SearchResponse response = rhlClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(response);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//查询删除--使用restClient
public void delete() {
String index = "demo2";
String type = "_doc";
String endPoint = "/" + index + "/" + type +"/_delete_by_query";
String source = genereateQueryString();
HttpEntity entity = new NStringEntity(source, ContentType.APPLICATION_JSON);
try {
Request request = new Request("POST", endPoint);
request.setEntity(entity);
restClient.performRequest(request);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public String genereateQueryString(){
IndexRequest indexRequest = new IndexRequest();
XContentBuilder builder;
try {
builder = JsonXContent.contentBuilder()
.startObject()
.startObject("query")
.startObject("bool")
.startArray("filter")
.startObject()
.startObject("term")
.field("tag","军事")
.endObject()
.endObject()
.startObject()
.startObject("range")
.startObject("publishTime")
.field("gte","2018-01-23T08:00:00Z")
.field("lte","2018-01-26T20:00:00Z")
.endObject()
.endObject()
.endObject()
.endArray()
.endObject()
.endObject()
.endObject();
indexRequest.source(builder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String source = indexRequest.source().utf8ToString();
return source;
}
//查询删除--deleteByQuery方法api,es6.5之后的版本直接支持,但是其实质还是使用的restClient去执行deleteByQuery方法
public void deleteByQuery(){
DeleteByQueryRequest request = new DeleteByQueryRequest("demo2");
request.types("_doc");
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", "中国");
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("tag", "军事");
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("publishTime");
rangeQueryBuilder.gte("2018-01-23T08:00:00Z");
rangeQueryBuilder.lte("2018-01-26T20:00:00Z");
BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
boolBuilder.must(matchQueryBuilder);
boolBuilder.must(termQueryBuilder);
boolBuilder.must(rangeQueryBuilder);
request.setQuery(boolBuilder);
request.setConflicts("proceed");
try {
BulkByScrollResponse bulkResponse = rhlClient.deleteByQuery(request, RequestOptions.DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
}
}
以上就是如何使用java high level rest client高版本实现对es的相关操作,只是个中案例,不全面,还请多多理解,如有不对指出,欢迎指正!