[Elasticsearch - Java] Java REST Client
Một trong những hạn chế của Elasticsearch Java Client API là yêu cầu phải tương thích về mặt binary với phiên bản của Elasticsearch (dù chạy dưới dạng standalone hay cluster).
May mắn thay, kể từ phiên bản 5.0.0, Elasticsearch đã cung cấp một tùy chọn khác: Java REST Client. API này giao tiếp với Elasticsearch thông qua giao thức HTTP, gọi trực tiếp vào các RESTful API endpoints, và quan trọng nhất là không phụ thuộc vào phiên bản Elasticsearch – nghĩa là nó tương thích với tất cả các phiên bản.
Tuy nhiên, Java REST Client hoạt động ở mức độ khá thấp, không thuận tiện như Java Client API. Dù vậy, có một số lý do khiến bạn có thể muốn sử dụng nó thay vì Java Client API, vì vậy chúng ta sẽ tìm hiểu kỹ hơn về cách sử dụng nó.
Thêm Dependency Vào Maven
Trước tiên, chúng ta cần thêm dependency vào Apache Maven trong tệp pom.xml
:
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>rest</artifactId>
<version>5.2.0</version>
</dependency>
Cấu Hình Java REST Client Trong Spring Framework
Để cấu hình RestClient, chúng ta chỉ cần khởi tạo một instance bằng phương thức .builder()
, như sau:
@Configuration
public class ElasticsearchClientConfiguration {
@Bean(destroyMethod = "close")
RestClient restClient() {
return RestClient
.builder(new HttpHost("localhost", 9200))
.setRequestConfigCallback(builder ->
builder.setConnectTimeout(1000)
.setSocketTimeout(5000)
)
.build();
}
}
Lưu ý rằng Java REST Client không hỗ trợ thiết lập timeout ở mức per-request, do đó chúng ta phải định cấu hình connect timeout và socket timeout ngay từ khi khởi tạo.
So Sánh Java Client API Và Java REST Client
Chúng ta sẽ so sánh hai phương pháp bằng cách thực hiện một số tác vụ tương tự trên Elasticsearch.
1. Kiểm Tra Trạng Thái Cluster
Sử dụng Java REST Client:
@Test
public void esClusterIsHealthy() throws Exception {
final Response response = client
.performRequest(HttpGet.METHOD_NAME, "_cluster/health", Collections.emptyMap());
final Object json = defaultConfiguration()
.jsonProvider()
.parse(EntityUtils.toString(response.getEntity()));
assertThat(json, hasJsonPath("$.status", equalTo("green")));
}
Ở đây, ta sử dụng Apache HTTP Client để gửi request HTTP GET và xử lý phản hồi ở dạng JSON.
2. Indexing A Document
Cách đơn giản nhất để biểu diễn cấu trúc JSON trong Java là sử dụng Map<String, Object>, như sau:
final Map<String, Object> source = new LinkedHashMap<>();
source.put("title", "Elasticsearch: The Definitive Guide");
source.put("categories", new Map[] {
Collections.singletonMap("name", "analytics"),
Collections.singletonMap("name", "search"),
Collections.singletonMap("name", "database store")
});
source.put("publisher", "O’Reilly");
source.put("description", "A comprehensive guide to Elasticsearch.");
source.put("published_date", "2015-02-07");
source.put("isbn", "978-1449358549");
source.put("rating", 4);
Sau đó, chúng ta chuyển đổi Map này thành JSON string bằng json-smart library:
final HttpEntity payload = new NStringEntity(
JSONObject.toJSONString(source),
ContentType.APPLICATION_JSON
);
Và gửi request để index tài liệu:
client.performRequestAsync(
HttpPut.METHOD_NAME,
"catalog/books/978-1449358549",
Collections.emptyMap(),
payload,
new ResponseListener() {
@Override
public void onSuccess(Response response) {
LOG.info("The document has been indexed successfully");
}
@Override
public void onFailure(Exception ex) {
LOG.error("The document has not been indexed", ex);
}
}
);
Lần này, thay vì đợi phản hồi synchronously, chúng ta sử dụng một callback (ResponseListener
) để xử lý phản hồi theo kiểu asynchronous.
Tìm Kiếm Dữ Liệu Bằng Java REST Client
Khác với Java Client API, Java REST Client không hỗ trợ fluent APIs để xây dựng Query DSL, vì vậy chúng ta phải tự cấu trúc truy vấn bằng Map<String, Object>.
final Map<String, Object> query = new LinkedHashMap<>();
query.put("size", 10);
query.put("_source", new String[] { "title", "publisher" });
query.put("query", Collections.singletonMap("bool", Collections.singletonMap("must", new Map[] {
Collections.singletonMap("range", Collections.singletonMap("rating", Collections.singletonMap("gte", 4))),
Collections.singletonMap("has_child", Collections.singletonMap("type", "authors")),
Collections.singletonMap("nested", Collections.singletonMap("path", "categories"))
})));
Chuyển đổi truy vấn thành JSON string và gửi request:
final HttpEntity payload = new NStringEntity(
JSONObject.toJSONString(query),
ContentType.APPLICATION_JSON
);
final Response response = client.performRequest(
HttpPost.METHOD_NAME,
"catalog/books/_search",
Collections.emptyMap(),
payload
);
final Object json = defaultConfiguration()
.jsonProvider()
.parse(EntityUtils.toString(response.getEntity()));
assertThat(json, hasJsonPath("$.hits.hits[0]._source.title", containsString("Elasticsearch: The Definitive Guide")));
Tóm Lược
Ưu điểm của Java REST Client
- Tương thích với mọi phiên bản Elasticsearch.
- Dựa trên HTTP, dễ tích hợp với các hệ thống khác.
- Hỗ trợ asynchronous API để xử lý request không đồng bộ.
Nhược điểm của Java REST Client
- Không thân thiện như Java Client API.
- Không hỗ trợ Query DSL dạng fluent API.
- Phản hồi dưới dạng raw JSON, cần xử lý thêm để trích xuất dữ liệu.
Mặc dù Java Client API vẫn là lựa chọn chính cho nhiều ứng dụng, Java REST Client mang lại sự linh hoạt và không bị ràng buộc vào phiên bản Elasticsearch, làm cho nó trở thành một giải pháp tiềm năng cho nhiều trường hợp sử dụng. 🚀
All rights reserved