使用Elasticsearch的方式
Elasticsearch有很多第三方java客户端
- TransportClient
- Jest
- Spring Data Elasticsearch(Spring Data 对 Elasticsearch 的整合)
springboot集成ES有两种方式:第一种方式是spring-boot-starter-data-elasticsearch,属于springboot官方的整合包,使用更方便但更新缓慢,支持的版本较低;第二种方式是Spring-data-elasticsearch,对版本的支持稍微好一点,但对于新版本还是支持的比较差。 - 官方的Java REST Client(项目中使用了这种方式)
Elasticsearch有两种连接方式:transport、rest。
transport通过TCP方式访问ES(只支持java,transport在8.x的版本中废弃),rest方式通过Http API访问ES(没有语言限制)。
** Java REST Client有两种版本:**- Java Low Level REST Client
- Java High Level REST Client(推荐,与ES发布周期相同)
两者原理基本一致,区别最大的就是封装性。 Low Level REST Client的各种操作都要自己封装,并且Java本身不支持json还需要引用第三方包。High Level REST Client是针对Elasticsearch api进行的高级封装,内部仍然是基于低级客户端,每个API都能够同步或异步调用。
兼容性
使用 High Level REST Client 与 Elasticsearch 进行通信,主版本号需要一致,次版本号不必相同,因为它是向前兼容的。次版本号小于等于Elasticsearch的都可以。这意味着它支持与更高版本的Elasticsearch进行通信。
Maven 配置
高级客户端依赖于以下部件及其传递依赖关系:
(1)org.elasticsearch.client:elasticsearch-rest-client
(2)org.elasticsearch:elasticsearch
pom.xml(版本号处要按下面形式展示,直接写具体版本号会报错)
<!--elasticsearch-rest-high-level-client-->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<!-- Java High Level REST Client -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
ESConfig
package com.test.es.config;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig.*;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback;
import org.elasticsearch.client.RestClientBuilder.RequestConfigCallback;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
@Configuration
public class ESConfig {
private static String hosts = "10.237.79.147"; //集群地址,多个用,分隔
private static int port = 9200; //使用的端口号
private static String schema = "http"; //使用的协议
private static ArrayList hostList = null;
private static int connectTimeOut = 1000;//连接超时时间
private static int socketTimeOut = 30000;//??
private static int connectionRequestTimeOut = 500;//获取连接的超时时间
private static int maxConnectNum = 100;//最大连接数
private static int maxConnectPerRoute = 100;//最大路由连接数
static {
hostList = new ArrayList<>();
String[] hostStrs = hosts.split(",");
for (String host:hostStrs){
hostList.add(new HttpHost(host,port,schema));
}
}
@Bean
public RestHighLevelClient client(){
RestClientBuilder builder = RestClient.builder((HttpHost[])hostList.toArray(new HttpHost[0]));
//异步httpclient连接延时配置
builder.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
@Override
public Builder customizeRequestConfig(Builder requestConfigBuilder) {
requestConfigBuilder.setConnectTimeout(connectTimeOut);
requestConfigBuilder.setSocketTimeout(socketTimeOut);
requestConfigBuilder.setConnectionRequestTimeout(connectionRequestTimeOut);
return requestConfigBuilder;
}
});
//异步httpclient连接数设置
builder.setHttpClientConfigCallback(new HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
httpClientBuilder.setMaxConnTotal(maxConnectNum);
httpClientBuilder.setMaxConnPerRoute(maxConnectPerRoute);
return httpClientBuilder;
}
});
RestHighLevelClient client = new RestHighLevelClient(builder);
return client;
}
}
model(Bean)
package com.test.es.model;
import lombok.Data;
@Data
public class Book {
private Integer id;
private String bookName;
private String author;
}
@Test
package com.test.es;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.test.es.model.Book;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.IOException;
@SpringBootTest
@RunWith(SpringRunner.class)
public class test {
/*第三种elastic elasticsearch-rest-high-level-client*/
@Autowired
private RestHighLevelClient client;
@Test
public void highLevelClient(){
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.from(0);
sourceBuilder.size(10);
//参数1:需要包含的内容;参数2:需要排除的内容
sourceBuilder.fetchSource(new String[]{"id","author","bookName"}, new String[]{});
//QueryBuilders类:创建搜索查询的实用工具类;matchQuery方法:参数1代表field name 参数2代表查询内容
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("author", "Author");
//???
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("tag", "体育");
//参数代表field name
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("publishTime");
rangeQueryBuilder.gte("2018-01-26T08:00:00Z");
rangeQueryBuilder.lte("2018-01-26T20:00:00Z");
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(matchQueryBuilder);
boolQueryBuilder.must(termQueryBuilder);
boolQueryBuilder.must(rangeQueryBuilder);
sourceBuilder.query(boolQueryBuilder);
SearchRequest searchRequest = new SearchRequest("springdataes_index");
// searchRequest.types(type);
searchRequest.source(sourceBuilder);
try {
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
SearchHit[] searchHits = hits.getHits();
for(SearchHit hit:searchHits){
System.out.println("search -> "+hit.getSourceAsString());
JSONObject bookJson = JSONObject.parseObject(hit.getSourceAsString());
Book book = JSON.toJavaObject(bookJson,Book.class);
System.out.println(book);
}
System.out.println(JSON.toJSONString(response));
}catch (IOException e){
e.printStackTrace();
}
}
@Test
public void highLevelClientDemo(){
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.fetchSource(new String[]{"id", "author", "bookName"}, new String[]{});
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("author", "Author");
MatchQueryBuilder matchQueryBuilder1 = QueryBuilders.matchQuery("id","2");
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(matchQueryBuilder).must(matchQueryBuilder1);
sourceBuilder.query(boolQueryBuilder);
//indices: springdataes_index => mysql的数据库
SearchRequest searchRequest = new SearchRequest("springdataes_index");
searchRequest.source(sourceBuilder);
try{
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
SearchHit[] searchHits = hits.getHits();
for(SearchHit hit:searchHits){
System.out.println("search ->"+hit.getSourceAsString());
JSONObject bookJson = JSONObject.parseObject(hit.getSourceAsString());
Book book = JSON.toJavaObject(bookJson,Book.class);
System.out.println(book);
}
}catch (IOException e){
e.printStackTrace();
}
}
@Test
public void highLevelClientdemo1(){
//第一部分
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.fetchSource(new String[]{"log_level","log_thread","log_date","log_class","log_content"}, new String[]{});
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("log_content","xx1");
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(matchQueryBuilder);
sourceBuilder.query(boolQueryBuilder);
//第二部分
//log-2019.11.24 数据库
SearchRequest searchRequest = new SearchRequest("log-2020.01.10");
searchRequest.source(sourceBuilder);
try {
SearchResponse response = client.search(searchRequest,RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
SearchHit[] searchHits = hits.getHits();
for(SearchHit hit:searchHits){
System.out.println("search -> "+hit.getSourceAsString());
/*上节基于ELK的日志搜索
search -> {"log_thread":"restartedMain","log_date":"2019-03-21 09:20:01,104","log_level":"INFO","log_class":"com.xxx.xxx.XXXApplication","log_content":"xx1"}
*/
}
}catch (IOException e){
e.printStackTrace();
}
}
@Test
public void update() throws IOException{
String index = "springdataes_index";
String type = "";
Book update_book = new Book();
update_book.setId(1);
update_book.setAuthor("UpdatedAuthor");
UpdateRequest request = new UpdateRequest(index, update_book.getId().toString());
request.doc(JSON.toJSONString(update_book), XContentType.JSON);
UpdateResponse updateResponse = client.update(request, RequestOptions.DEFAULT);
System.out.println("update: "+JSON.toJSONString(updateResponse));
}
}
Java High Level REST Client官网API介绍
Java High Level REST Client官网API
- matchQuery:会将搜索词分词,再与目标查询字段进行匹配,若分词中的任意一个词与目标字段匹配上,则可查询到。
- termQuery:不会对搜索词进行分词处理,而是作为一个整体与目标字段进行匹配,若完全匹配,则可查询到。