ElasticSearch Java API 之 High Level REST Client

ElasticSearch Java API 之 High Level REST Client

Elasticsearch 官方的 High Level REST Client 在 7.1.5.0 版本废弃。所以本文中的 API 不推荐使用。

快速开始

引入依赖

在 pom.xml 中引入以下依赖:

1
2
3
4
5
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.17.1</version>
</dependency>

创建连接和关闭

1
2
3
4
5
6
7
8
// 创建连接
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http"),
new HttpHost("localhost", 9201, "http")));

// 关闭
client.close();

索引 API

测试准备

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static final String INDEX = "mytest";
public static final String INDEX_ALIAS = "mytest_alias";
/**
* {@link User} 的 mapping 结构(json形式)
*/
public static final String MAPPING_JSON =
"{\n" + " \"properties\": {\n" + " \"_class\": {\n" + " \"type\": \"keyword\",\n"
+ " \"index\": false,\n" + " \"doc_values\": false\n" + " },\n" + " \"description\": {\n"
+ " \"type\": \"text\",\n" + " \"fielddata\": true\n" + " },\n" + " \"enabled\": {\n"
+ " \"type\": \"boolean\"\n" + " },\n" + " \"name\": {\n" + " \"type\": \"text\",\n"
+ " \"fielddata\": true\n" + " }\n" + " }\n" + "}";

@Autowired
private RestHighLevelClient client;

创建索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 创建索引
CreateIndexRequest createIndexRequest = new CreateIndexRequest(INDEX);

// 设置索引的 settings
createIndexRequest.settings(
Settings.builder().put("index.number_of_shards", 3).put("index.number_of_replicas", 2));

// 设置索引的 mapping
createIndexRequest.mapping(MAPPING_JSON, XContentType.JSON);

// 设置索引的别名
createIndexRequest.alias(new Alias(INDEX_ALIAS));

AcknowledgedResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
Assertions.assertTrue(createIndexResponse.isAcknowledged());

删除索引

1
2
3
4
// 删除索引
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(INDEX);
AcknowledgedResponse deleteResponse = client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
Assertions.assertTrue(deleteResponse.isAcknowledged());

判断索引是否存在

1
2
3
4
GetIndexRequest getIndexRequest = new GetIndexRequest(INDEX);
Assertions.assertTrue(client.indices().exists(getIndexRequest, RequestOptions.DEFAULT));
GetIndexRequest getIndexAliasRequest = new GetIndexRequest(INDEX_ALIAS);
Assertions.assertTrue(client.indices().exists(getIndexAliasRequest, RequestOptions.DEFAULT));

文档 API

文档测试准备

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public static final String INDEX = "mytest";
public static final String INDEX_ALIAS = "mytest_alias";
/**
* {@link User} 的 mapping 结构(json形式)
*/
public static final String MAPPING_JSON =
"{\n" + " \"properties\": {\n" + " \"_class\": {\n" + " \"type\": \"keyword\",\n"
+ " \"index\": false,\n" + " \"doc_values\": false\n" + " },\n" + " \"description\": {\n"
+ " \"type\": \"text\",\n" + " \"fielddata\": true\n" + " },\n" + " \"enabled\": {\n"
+ " \"type\": \"boolean\"\n" + " },\n" + " \"name\": {\n" + " \"type\": \"text\",\n"
+ " \"fielddata\": true\n" + " }\n" + " }\n" + "}";

@Autowired
private RestHighLevelClient client;

@BeforeEach
public void init() throws IOException {

// 创建索引
CreateIndexRequest createIndexRequest = new CreateIndexRequest(INDEX);

// 设置索引的 settings
createIndexRequest.settings(
Settings.builder().put("index.number_of_shards", 3).put("index.number_of_replicas", 2));

// 设置索引的 mapping
createIndexRequest.mapping(MAPPING_JSON, XContentType.JSON);

// 设置索引的别名
createIndexRequest.alias(new Alias(INDEX_ALIAS));

AcknowledgedResponse response = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
Assertions.assertTrue(response.isAcknowledged());

// 判断索引是否存在
GetIndexRequest getIndexRequest = new GetIndexRequest(INDEX_ALIAS);
Assertions.assertTrue(client.indices().exists(getIndexRequest, RequestOptions.DEFAULT));
GetIndexRequest getIndexAliasRequest = new GetIndexRequest(INDEX_ALIAS);
Assertions.assertTrue(client.indices().exists(getIndexAliasRequest, RequestOptions.DEFAULT));
}

@AfterEach
public void destroy() throws IOException {
// 删除索引
DeleteIndexRequest request = new DeleteIndexRequest(INDEX);
AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
Assertions.assertTrue(response.isAcknowledged());
}

创建文档

RestHighLevelClient Api 使用 IndexRequest 来构建创建文档的请求参数。

【示例】创建 id 为 1 的文档

1
2
3
4
5
6
7
8
IndexRequest request = new IndexRequest("product");
request.id("1");
Product product = new Product();
product.setName("机器人");
product.setDescription("人工智能机器人");
product.setEnabled(true);
String jsonString = JSONUtil.toJsonStr(product);
request.source(jsonString, XContentType.JSON);

同步执行

1
IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);

异步执行

1
2
3
4
5
6
7
8
9
10
11
12
// 异步执行
client.indexAsync(request, RequestOptions.DEFAULT, new ActionListener<IndexResponse>() {
@Override
public void onResponse(IndexResponse indexResponse) {
System.out.println(indexResponse);
}

@Override
public void onFailure(Exception e) {
System.out.println("执行失败");
}
});

删除文档

RestHighLevelClient Api 使用 DeleteRequest 来构建删除文档的请求参数。

【示例】删除 id 为 1 的文档

1
DeleteRequest deleteRequest = new DeleteRequest(INDEX_ALIAS, "1");

同步执行

1
2
DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT);
System.out.println(deleteResponse);

异步执行

1
2
3
4
5
6
7
8
9
10
11
client.deleteAsync(deleteRequest, RequestOptions.DEFAULT, new ActionListener<DeleteResponse>() {
@Override
public void onResponse(DeleteResponse deleteResponse) {
System.out.println(deleteResponse);
}

@Override
public void onFailure(Exception e) {
System.out.println("执行失败");
}
});

更新文档

RestHighLevelClient Api 使用 UpdateRequest 来构建更新文档的请求参数。

【示例】更新 id 为 1 的文档

1
2
3
4
5
6
7
UpdateRequest updateRequest = new UpdateRequest(INDEX_ALIAS, "1");
Product product3 = new Product();
product3.setName("扫地机器人");
product3.setDescription("人工智能扫地机器人");
product3.setEnabled(true);
String jsonString2 = JSONUtil.toJsonStr(product3);
updateRequest.doc(jsonString2, XContentType.JSON);

同步执行

1
2
UpdateResponse updateResponse = client.update(updateRequest, RequestOptions.DEFAULT);
System.out.println(updateResponse);

异步执行

1
2
3
4
5
6
7
8
9
10
11
client.updateAsync(updateRequest, RequestOptions.DEFAULT, new ActionListener<UpdateResponse>() {
@Override
public void onResponse(UpdateResponse updateResponse) {
System.out.println(updateResponse);
}

@Override
public void onFailure(Exception e) {
System.out.println("执行失败");
}
});

查看文档

RestHighLevelClient Api 使用 GetRequest 来构建查看文档的请求参数。

【示例】查看 id 为 1 的文档

1
GetRequest getRequest = new GetRequest(INDEX_ALIAS, "1");

同步执行

1
GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);

异步执行

1
2
3
4
5
6
7
8
9
10
11
client.getAsync(getRequest, RequestOptions.DEFAULT, new ActionListener<GetResponse>() {
@Override
public void onResponse(GetResponse getResponse) {
System.out.println(getResponse);
}

@Override
public void onFailure(Exception e) {
System.out.println("执行失败");
}
});

获取匹配条件的记录总数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Test
@DisplayName("获取匹配条件的记录总数")
public void count() throws IOException {
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchPhraseQuery("customer_gender", "MALE"));
sourceBuilder.trackTotalHits(true);

CountRequest countRequest = new CountRequest(INDEX);
countRequest.source(sourceBuilder);

CountResponse countResponse = client.count(countRequest, RequestOptions.DEFAULT);
long count = countResponse.getCount();
System.out.println("命中记录数:" + count);
}

分页查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@ParameterizedTest
@ValueSource(ints = {0, 1, 2, 3})
@DisplayName("分页查询测试")
public void pageTest(int page) throws IOException {

int size = 10;
int offset = page * size;
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchPhraseQuery("customer_gender", "MALE"));
sourceBuilder.from(offset);
sourceBuilder.size(size);
sourceBuilder.trackTotalHits(true);

SearchRequest searchRequest = new SearchRequest(INDEX);
searchRequest.source(sourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHit[] hits = response.getHits().getHits();
for (SearchHit hit : hits) {
KibanaSampleDataEcommerceBean bean =
BeanUtil.mapToBean(hit.getSourceAsMap(), KibanaSampleDataEcommerceBean.class, true,
CopyOptions.create());
System.out.println(bean);
}
}

条件查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Test
@DisplayName("条件查询")
public void matchPhraseQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest(INDEX);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("customer_last_name", "Jensen"));
sourceBuilder.query(boolQueryBuilder);
sourceBuilder.trackTotalHits(true);
searchRequest.source(sourceBuilder);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHit[] hits = response.getHits().getHits();
for (SearchHit hit : hits) {
KibanaSampleDataEcommerceBean bean =
BeanUtil.mapToBean(hit.getSourceAsMap(), KibanaSampleDataEcommerceBean.class, true,
CopyOptions.create());
System.out.println(bean);
}
}

参考资料