Java客户端
在Elasticsearch中,为java提供了2种客户端,一种是REST风格的客户端,另一种是Java API的客户端。
官网:https://www.elastic.co/guide/en/elasticsearch/client/index.html
REST客户端
Elasticsearch提供了2种REST客户端,一种是低级客户端,一种是高级客户端。
Java Low Level REST Client: 官方提供的低级客户端。该客户端通过http来连接Elasticsearch集群。用户在使 用该客户端时需要将请求数据手动拼接成Elasticsearch所需JSON格式进行发送,收到响应时同样也需要将返回 的JSON数据手动封装成对象。虽然麻烦,不过该客户端兼容所有的Elasticsearch版本。
Java High Level REST Client: 官方提供的高级客户端。该客户端基于低级客户端实现,它提供了很多便捷的 API来解决低级客户端需要手动转换数据格式的问题。
示例数据
1 POST /house/_bulk
2
3 {"index":{"_index":"house"}}
4 {"id":"1001","title":"整租 · 南丹大楼 1居室 7500","price":"7500"}
5 {"index":{"_index":"house"}}
6 {"id":"1002","title":"陆家嘴板块,精装设计一室一厅,可拎包入住诚意租。","price":"8500"}
7 {"index":{"_index":"house"}}
8 {"id":"1003","title":"整租 · 健安坊 1居室 4050","price":"7500"}
9 {"index":{"_index":"house"}}
10 {"id":"1004","title":"整租 · 中凯城市之光+视野开阔+景色秀丽+拎包入住","price":"6500"}
11 {"index":{"_index":"house"}}
12 {"id":"1005","title":"整租 · 南京西路品质小区 21213三轨交汇 配套齐* 拎包入住","price":"6000"}
13 {"index":{"_index":"house"}}
14 {"id":"1006","title":"祥康里 简约风格 *南户型 拎包入住 看房随时","price":"7000"}
REST低级客户端
测试elasticsearch版本是:7.6.1
1、创建工程test-springboot-elasticsearch,引入依赖
1 <!-- elasticsearch -->
2 <dependency>
3 <groupId>org.elasticsearch.client</groupId>
4 <artifactId>elasticsearch-rest-client</artifactId>
5 <version>7.6.1</version>
6 </dependency>
完整依赖如下:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 <modelVersion>4.0.0</modelVersion>
6
7 <groupId>com.test</groupId>
8 <artifactId>test-springboot-es</artifactId>
9 <version>1.0-SNAPSHOT</version>
10
11 <parent>
12 <groupId>org.springframework.boot</groupId>
13 <artifactId>spring-boot-starter-parent</artifactId>
14 <version>2.2.5.RELEASE</version>
15 </parent>
16
17 <properties>
18 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
19 <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
20 <java.version>1.8</java.version>
21 </properties>
22
23 <dependencies>
24
25 <dependency>
26 <groupId>org.springframework.boot</groupId>
27 <artifactId>spring-boot-starter-web</artifactId>
28 </dependency>
29
30 <dependency>
31 <groupId>org.elasticsearch.client</groupId>
32 <artifactId>elasticsearch-rest-client</artifactId>
33 <version>7.6.1</version>
34 </dependency>
35
36
37 <dependency>
38 <groupId>org.springframework.boot</groupId>
39 <artifactId>spring-boot-starter-test</artifactId>
40 <scope>test</scope>
41 </dependency>
42
43 </dependencies>
44
45
46 <!-- SpringBoot打包插件,可以将代码打包成一个可执行的jar包 -->
47 <build>
48 <plugins>
49 <plugin>
50 <groupId>org.springframework.boot</groupId>
51 <artifactId>spring-boot-maven-plugin</artifactId>
52 </plugin>
53 </plugins>
54 </build>
55 </project>
View Code
2、编写测试用例
1 package com.test.springboot.es;
2
3 import com.fasterxml.jackson.databind.ObjectMapper;
4 import org.apache.http.HttpHost;
5 import org.apache.http.util.EntityUtils;
6 import org.elasticsearch.client.*;
7 import org.junit.After;
8 import org.junit.Before;
9 import org.junit.Test;
10
11 import java.io.IOException;
12 import java.util.HashMap;
13 import java.util.Map;
14
15 public class TestLowRestClient {
16
17 private static final ObjectMapper MAPPER = new ObjectMapper();
18 private RestClient restClient;
19
20 @Before
21 public void init() {
22 RestClientBuilder restClientBuilder = RestClient.builder(
23 new HttpHost("127.0.0.1", 19201, "http"),
24 new HttpHost("127.0.0.1", 19202, "http"),
25 new HttpHost("127.0.0.1", 19203, "http"));
26 restClientBuilder.setFailureListener(new RestClient.FailureListener() {
27 @Override
28 public void onFailure(Node node) {
29 System.out.println("出错了 -> " + node);
30 }
31 });
32 this.restClient = restClientBuilder.build();
33 }
34
35 @After
36 public void after() throws IOException {
37 restClient.close();
38 }
39
40 // 查询集群状态
41 @Test
42 public void testGetInfo() throws IOException {
43 Request request = new Request("GET", "/_cluster/state");
44 request.addParameter("pretty", "true");
45 Response response = this.restClient.performRequest(request);
46 System.out.println(response.getStatusLine());
47 System.out.println(EntityUtils.toString(response.getEntity()));
48 }
49
50
51 // 新增数据
52 @Test
53 public void testCreateData() throws IOException {
54 Request request = new Request("POST", "/house/_doc");
55 Map<String, Object> data = new HashMap<>();
56 data.put("id", "2001");
57 data.put("title", "张江高科");
58 data.put("price", "3500");
59 request.setJsonEntity(MAPPER.writeValueAsString(data));
60 Response response = this.restClient.performRequest(request);
61 System.out.println(response.getStatusLine());
62 System.out.println(EntityUtils.toString(response.getEntity()));
63 }
64
65
66 // 根据id查询数据
67 @Test
68 public void testQueryData() throws IOException {
69 Request request = new Request("GET", "/house/_doc/i7I4snIB-J-F9-0D3D6H");
70 Response response = this.restClient.performRequest(request);
71 System.out.println(response.getStatusLine());
72 System.out.println(EntityUtils.toString(response.getEntity()));
73 }
74
75 // 搜索数据
76 @Test
77 public void testSearchData() throws IOException {
78 Request request = new Request("POST", "/house/_search");
79 String searchJson = "{\"query\": {\"match\": {\"title\": \"拎包入住\"}}}";
80 request.setJsonEntity(searchJson);
81 request.addParameter("pretty", "true");
82 Response response = this.restClient.performRequest(request);
83 System.out.println(response.getStatusLine());
84 System.out.println(EntityUtils.toString(response.getEntity()));
85 }
86
87 }
3、测试
分别测试以上方法,均能正常返回
从使用中,可以看出,基本和我们使用RESTful api使用几乎是一致的。
REST高级客户端
1、在工程共新增高级客户端依赖
1 <dependency>
2 <groupId>org.elasticsearch.client</groupId>
3 <artifactId>elasticsearch-rest-high-level-client</artifactId>
4 <version>7.6.1</version>
5 <exclusions>
6 <exclusion>
7 <groupId>org.elasticsearch</groupId>
8 <artifactId>elasticsearch</artifactId>
9 </exclusion>
10 </exclusions>
11 </dependency>
12 <dependency>
13 <groupId>org.elasticsearch</groupId>
14 <artifactId>elasticsearch</artifactId>
15 <version>7.6.1</version>
16 </dependency>
17
18 <dependency>
19 <groupId>org.elasticsearch.client</groupId>
20 <artifactId>elasticsearch-rest-client</artifactId>
21 <version>7.6.1</version>
22 </dependency>
2、编写测试用例
1 package com.test.springboot.es;
2
3 import com.fasterxml.jackson.databind.ObjectMapper;
4 import org.apache.http.HttpHost;
5 import org.apache.http.util.EntityUtils;
6 import org.elasticsearch.action.ActionListener;
7 import org.elasticsearch.action.delete.DeleteRequest;
8 import org.elasticsearch.action.delete.DeleteResponse;
9 import org.elasticsearch.action.get.GetRequest;
10 import org.elasticsearch.action.get.GetResponse;
11 import org.elasticsearch.action.index.IndexRequest;
12 import org.elasticsearch.action.index.IndexResponse;
13 import org.elasticsearch.action.search.SearchRequest;
14 import org.elasticsearch.action.search.SearchResponse;
15 import org.elasticsearch.action.update.UpdateRequest;
16 import org.elasticsearch.action.update.UpdateResponse;
17 import org.elasticsearch.client.*;
18 import org.elasticsearch.common.Strings;
19 import org.elasticsearch.common.unit.TimeValue;
20 import org.elasticsearch.index.query.QueryBuilders;
21 import org.elasticsearch.search.SearchHit;
22 import org.elasticsearch.search.SearchHits;
23 import org.elasticsearch.search.builder.SearchSourceBuilder;
24 import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
25 import org.junit.After;
26 import org.junit.Before;
27 import org.junit.Test;
28
29 import java.io.IOException;
30 import java.util.HashMap;
31 import java.util.Map;
32 import java.util.concurrent.TimeUnit;
33
34 public class TestHighRestClient {
35
36 private static final ObjectMapper MAPPER = new ObjectMapper();
37 private RestHighLevelClient restHighClient;
38
39 @Before
40 public void init() {
41
42 RestClientBuilder restClientBuilder = RestClient.builder(
43 new HttpHost("127.0.0.1", 19201, "http"),
44 new HttpHost("127.0.0.1", 19202, "http"),
45 new HttpHost("127.0.0.1", 19203, "http"));
46 restClientBuilder.setFailureListener(new RestClient.FailureListener() {
47 @Override
48 public void onFailure(Node node) {
49 System.out.println("出错了 -> " + node);
50 }
51 });
52
53 this.restHighClient = new RestHighLevelClient(restClientBuilder);
54 }
55
56 @After
57 public void after() throws IOException {
58 restHighClient.close();
59 }
60
61 // 新增文档,同步操作
62 @Test
63 public void testCreate() throws Exception {
64 Map<String, Object> data = new HashMap<>();
65 data.put("id", "2002");
66 data.put("title", "南京西路 拎包入住 一室一厅");
67 data.put("price", "4500");
68 IndexRequest indexRequest = new IndexRequest("house", "_doc").source(data);
69 IndexResponse indexResponse = restHighClient.index(indexRequest, RequestOptions.DEFAULT);
70 System.out.println("id->" + indexResponse.getId());
71 System.out.println("index->" + indexResponse.getIndex());
72 System.out.println("type->" + indexResponse.getType());
73 System.out.println("version->" + indexResponse.getVersion());
74 System.out.println("result->" + indexResponse.getResult());
75 System.out.println("shardInfo->" + indexResponse.getShardInfo());
76 }
77
78 // 新增文档,异步操作
79 @Test
80 public void testCreateAsync() throws Exception {
81 Map<String, Object> data = new HashMap<>();
82 data.put("id", "2003");
83 data.put("title", "南京东路 最新房源 二室一厅");
84 data.put("price", "5500");
85 IndexRequest indexRequest = new IndexRequest("house", "_doc").source(data);
86 restHighClient.indexAsync(indexRequest, RequestOptions.DEFAULT, new ActionListener<IndexResponse>() {
87 @Override
88 public void onResponse(IndexResponse indexResponse) {
89 System.out.println("id->" + indexResponse.getId());
90 System.out.println("index->" + indexResponse.getIndex());
91 System.out.println("type->" + indexResponse.getType());
92 System.out.println("version->" + indexResponse.getVersion());
93 System.out.println("result->" + indexResponse.getResult());
94 System.out.println("shardInfo->" + indexResponse.getShardInfo());
95 }
96
97 @Override
98 public void onFailure(Exception e) {
99 System.out.println(e);
100 }
101 });
102 System.out.println("ok");
103 Thread.sleep(20000);
104 }
105
106 // 测试查询
107 @Test
108 public void testQuery() throws Exception {
109 GetRequest getRequest = new GetRequest("house", "_doc",
110 "jLI5snIB-J-F9-0D8j7h");
111 // 指定返回的字段
112 String[] includes = new String[]{"title", "id"};
113 String[] excludes = Strings.EMPTY_ARRAY;
114 FetchSourceContext fetchSourceContext =
115 new FetchSourceContext(true, includes, excludes);
116 getRequest.fetchSourceContext(fetchSourceContext);
117 GetResponse response = restHighClient.get(getRequest, RequestOptions.DEFAULT);
118 System.out.println("数据 -> " + response.getSource());
119 }
120
121
122 // 判断是否存在
123 @Test
124 public void testExists() throws Exception {
125 GetRequest getRequest = new GetRequest("house", "_doc", "jLI5snIB-J-F9-0D8j7h"); // 不返回的字段
126 // 不返回的字段
127 getRequest.fetchSourceContext(new FetchSourceContext(false));
128 boolean exists = restHighClient.exists(getRequest, RequestOptions.DEFAULT);
129 System.out.println("exists -> " + exists);
130 }
131
132 // 删除数据
133 @Test
134 public void testDelete() throws Exception {
135
136 DeleteRequest deleteRequest = new DeleteRequest("house", "_doc",
137 "jLI5snIB-J-F9-0D8j7h");
138 DeleteResponse response = restHighClient.delete(deleteRequest,
139 RequestOptions.DEFAULT);
140 System.out.println(response.status());// OK or NOT_FOUND
141 }
142
143 // 更新数据
144 @Test
145 public void testUpdate() throws Exception {
146 UpdateRequest updateRequest = new UpdateRequest("house", "_doc",
147 "i7I4snIB-J-F9-0D3D6H");
148 Map<String, Object> data = new HashMap<>();
149 data.put("title", "张江高科2");
150 data.put("price", "5000");
151 updateRequest.doc(data);
152 UpdateResponse response = restHighClient.update(updateRequest, RequestOptions.DEFAULT);
153 System.out.println("version -> " + response.getVersion());
154 }
155
156
157 // 搜索数据
158 @Test
159 public void testSearch() throws Exception {
160 SearchRequest searchRequest = new SearchRequest("house");
161 searchRequest.types("_doc");
162 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
163 sourceBuilder.query(QueryBuilders.matchQuery("title", "拎包入住"));
164 sourceBuilder.from(0);
165 sourceBuilder.size(5);
166 sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
167 searchRequest.source(sourceBuilder);
168 SearchResponse search = restHighClient.search(searchRequest, RequestOptions.DEFAULT);
169 System.out.println("搜索到 " + search.getHits().getTotalHits().value + " 条数据.");
170 SearchHits hits = search.getHits();
171 for (SearchHit hit : hits) {
172 System.out.println(hit.getSourceAsString());
173 }
174 }
175 }
REST客户端与SpringBoot集成
测试elasticsearch版本是:7.6.1
集成原理:
在SpringBoot自动装配类(RestClientAutoConfiguration.class)中,导入Rest客户端配置类(RestClientConfigurations)中的静态类
1 @Configuration(proxyBeanMethods = false)
2 @ConditionalOnClass(RestClient.class)
3 @EnableConfigurationProperties(RestClientProperties.class)
4 @Import({ RestClientConfigurations.RestClientBuilderConfiguration.class,
5 RestClientConfigurations.RestHighLevelClientConfiguration.class,
6 RestClientConfigurations.RestClientFallbackConfiguration.class })
7 public class RestClientAutoConfiguration {
8
9 }
查看Rest客户端配置类(RestClientConfigurations)
1 class RestClientConfigurations {
2
3 ...
4
5 @Configuration(proxyBeanMethods = false)
6 @ConditionalOnClass(RestHighLevelClient.class)
7 static class RestHighLevelClientConfiguration {
8
9 // 高级客户端
10 @Bean
11 @ConditionalOnMissingBean
12 RestHighLevelClient elasticsearchRestHighLevelClient(RestClientBuilder restClientBuilder) {
13 return new RestHighLevelClient(restClientBuilder);
14 }
15
16 // 低级客户端
17 @Bean
18 @ConditionalOnMissingBean
19 RestClient elasticsearchRestClient(RestClientBuilder builder,
20 ObjectProvider<RestHighLevelClient> restHighLevelClient) {
21 RestHighLevelClient client = restHighLevelClient.getIfUnique();
22 if (client != null) {
23 return client.getLowLevelClient();
24 }
25 return builder.build();
26 }
27
28 }
29
30 ...
31
32 }
可以看到配置类中,自动配置类 ES低级客户端、ES高级客户端
集成
1、新建项目引入依赖,spring-boot-starter-data-elasticsearch
1 <!-- SpringBoot默认使用SpringData ElasticSearch模块进行操作 -->
2 <dependency>
3 <groupId>org.springframework.boot</groupId>
4 <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
5 </dependency>
完整依赖如下:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 <modelVersion>4.0.0</modelVersion>
6
7 <groupId>com.test</groupId>
8 <artifactId>test-springboot-es</artifactId>
9 <version>1.0-SNAPSHOT</version>
10
11 <parent>
12 <groupId>org.springframework.boot</groupId>
13 <artifactId>spring-boot-starter-parent</artifactId>
14 <version>2.2.5.RELEASE</version>
15 </parent>
16
17 <properties>
18
19 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
20 <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
21 <java.version>1.8</java.version>
22 </properties>
23
24 <dependencies>
25
26 <dependency>
27 <groupId>org.springframework.boot</groupId>
28 <artifactId>spring-boot-starter-web</artifactId>
29 </dependency>
30
31
32 <!-- SpringBoot默认使用SpringData ElasticSearch模块进行操作 -->
33 <dependency>
34 <groupId>org.springframework.boot</groupId>
35 <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
36 </dependency>
37
38 <dependency>
39 <groupId>org.springframework.boot</groupId>
40 <artifactId>spring-boot-starter-test</artifactId>
41 <scope>test</scope>
42 </dependency>
43
44 </dependencies>
45
46
47 <!-- SpringBoot打包插件,可以将代码打包成一个可执行的jar包 -->
48 <build>
49 <plugins>
50 <plugin>
51 <groupId>org.springframework.boot</groupId>
52 <artifactId>spring-boot-maven-plugin</artifactId>
53 </plugin>
54 </plugins>
55 </build>
56 </project>
View Code
2、编写测试用例
1 package com.test.springboot.es;
2
3
4 import org.apache.http.util.EntityUtils;
5 import org.elasticsearch.action.search.SearchRequest;
6 import org.elasticsearch.action.search.SearchResponse;
7 import org.elasticsearch.client.*;
8 import org.elasticsearch.common.unit.TimeValue;
9 import org.elasticsearch.index.query.QueryBuilders;
10 import org.elasticsearch.search.SearchHit;
11 import org.elasticsearch.search.SearchHits;
12 import org.elasticsearch.search.builder.SearchSourceBuilder;
13 import org.junit.Test;
14 import org.junit.runner.RunWith;
15 import org.springframework.beans.factory.annotation.Autowired;
16 import org.springframework.boot.test.context.SpringBootTest;
17 import org.springframework.test.context.junit4.SpringRunner;
18
19 import java.io.IOException;
20 import java.util.concurrent.TimeUnit;
21
22 @RunWith(SpringRunner.class)
23 @SpringBootTest
24 public class TestSpringBootES {
25
26 // 低级客户端
27 @Autowired
28 RestClient restClient;
29
30 // 高级客户端
31 @Autowired
32 RestHighLevelClient restHighLevelClient;
33
34 // 低级客户端搜索数据
35 @Test
36 public void testRestClientSearch() throws IOException {
37 Request request = new Request("POST", "/house/_search");
38 String searchJson = "{\"query\": {\"match\": {\"title\": \"拎包入住\"}}}";
39 request.setJsonEntity(searchJson);
40 request.addParameter("pretty", "true");
41 Response response = restClient.performRequest(request);
42 System.out.println(response.getStatusLine());
43 System.out.println(EntityUtils.toString(response.getEntity()));
44 }
45
46 // 高级客户端搜索数据
47 @Test
48 public void testRestHighLevelClientSearch() throws Exception {
49 SearchRequest searchRequest = new SearchRequest("house");
50 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
51 sourceBuilder.query(QueryBuilders.matchQuery("title", "拎包入住"));
52 sourceBuilder.from(0);
53 sourceBuilder.size(5);
54 sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
55 searchRequest.source(sourceBuilder);
56 SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
57 System.out.println("搜索到 " + search.getHits().getTotalHits() + " 条数据.");
58 SearchHits hits = search.getHits();
59 for (SearchHit hit : hits) {
60 System.out.println(hit.getSourceAsString());
61 }
62 }
63 }
3、编辑application.yml文件
1 spring:
2 elasticsearch:
3 rest:
4 uris: http://127.0.0.1:9200
4、测试验证, 测试方法皆运行成功,证明ES低级客户端、ES高级客户端皆有效