使用 Quarkus 連接到 Elasticsearch
1. 概述
Quarkus 是一個現代框架,可以輕鬆愉快地建立高效能應用程式。在本教程中,我們將探討如何將 Quarkus 與 Elasticsearch(一個著名的全文搜尋引擎和 NoSQL 資料儲存)整合。
2. 依賴和配置
一旦我們在本地主機上運行了 Elasticsearch 實例,我們就將依賴項新增至 Quarkus 應用程式:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-elasticsearch-rest-client</artifactId>
<version>${quarkus.version}</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-elasticsearch-java-client</artifactId>
<version>${quarkus.version}</version>
</dependency>
我們新增了quarkus-elasticsearch-rest-client依賴項,它為我們帶來了低階 Elasticsearch REST 用戶端。除此之外,我們還附加了quarkus-elasticsearch-java-client依賴項,這使我們能夠使用 Elasticsearch Java 用戶端。在我們的應用程式中,我們可以選擇最適合我們需求的選項。
下一步,讓我們將 Elasticsearch 主機新增至application.properties檔案:
quarkus.elasticsearch.hosts=localhost:9200
現在我們準備開始在 Quarkus 應用程式中使用 Elasticsearch。所有必需的 bean 將由ElasticsearchRestClientProducer和ElasticsearchJavaClientProducer在背景自動建立。
3.Elasticsearch低級REST客戶端
我們可以使用Elasticsearch 低階 REST 客戶端將我們的應用程式與 Elasticsearch 整合。這使我們能夠完全控制序列化和反序列化過程,並允許我們使用 JSON 為 Elasticsearch 建立查詢。
讓我們建立一個要在應用程式中建立索引的模型:
public class StoreItem {
private String id;
private String name;
private Long price;
//getters and setters
}
在我們的模型中,我們有一個文檔 ID 欄位。此外,我們還添加了一些欄位以方便搜尋。
現在,讓我們新增方法來索引我們的StoreItem :
private void indexUsingRestClient() throws IOException, InterruptedException {
iosPhone = new StoreItem();
iosPhone.setId(UUID.randomUUID().toString());
iosPhone.setPrice(1000L);
iosPhone.setName("IOS smartphone");
Request restRequest = new Request(
"PUT",
"/store-items/_doc/" + iosPhone.getId());
restRequest.setJsonEntity(JsonObject.mapFrom(iosPhone).toString());
restClient.performRequest(restRequest);
}
在這裡,我們建立了一個具有隨機 ID 和特定名稱的StoreItem 。然後我們對/store-items/_doc/{id}路徑執行 PUT 請求以索引我們的文件。現在我們將建立一個方法來驗證文件的索引方式並透過各個欄位搜尋它們:
@Test
void givenRestClient_whenSearchInStoreItemsByName_thenExpectedDocumentsFound() throws Exception {
indexUsingRestClient();
Request request = new Request(
"GET",
"/store-items/_search");
JsonObject termJson = new JsonObject().put("name", "IOS smartphone");
JsonObject matchJson = new JsonObject().put("match", termJson);
JsonObject queryJson = new JsonObject().put("query", matchJson);
request.setJsonEntity(queryJson.encode());
Response response = restClient.performRequest(request);
String responseBody = EntityUtils.toString(response.getEntity());
JsonObject json = new JsonObject(responseBody);
JsonArray hits = json.getJsonObject("hits").getJsonArray("hits");
List<StoreItem> results = new ArrayList<>(hits.size());
for (int i = 0; i < hits.size(); i++) {
JsonObject hit = hits.getJsonObject(i);
StoreItem fruit = hit.getJsonObject("_source").mapTo(StoreItem.class);
results.add(fruit);
}
assertThat(results)
.hasSize(1)
.containsExactlyInAnyOrder(iosPhone);
}
我們使用indexUsingRestClient()方法對StoreItem建立索引。然後,我們建立 JSON 查詢並執行搜尋請求。我們反序列化每個搜尋命中並驗證它是否包含我們的StoreItem 。
這樣,我們就使用低階 REST 用戶端在 Quarkus 應用程式中實現了與 Elasticsearch 的基本整合。正如我們所看到的,我們需要自己處理所有的序列化和反序列化過程。
4.Elasticsearch Java 客戶端
Elasticsearch Java 用戶端是一個更高階的客戶端。我們可以使用它的 DSL 語法來更優雅地建立 Elasticsearch 查詢。
讓我們建立一個方法來使用此客戶端索引我們的StoreItem :
private void indexUsingElasticsearchClient() throws IOException, InterruptedException {
androidPhone = new StoreItem();
androidPhone.setId(UUID.randomUUID().toString());
androidPhone.setPrice(500L);
androidPhone.setName("Android smartphone");
IndexRequest<StoreItem> request = IndexRequest.of(
b -> b.index("store-items")
.id(androidPhone.getId())
.document(androidPhone));
elasticsearchClient.index(request);
}
我們建立了另一個StoreItem並創建了[IndexRequest](https://artifacts.elastic.co/javadoc/co/elastic/clients/elasticsearch-java/8.14.3/co/elastic/clients/elasticsearch/core/IndexRequest.html) 。然後我們呼叫Elasticsearch Java Client的index()方法來執行請求。
現在讓我們搜尋我們儲存的項目:
@Test
void givenElasticsearchClient_whenSearchInStoreItemsByName_thenExpectedDocumentsFound() throws Exception {
indexUsingElasticsearchClient();
Query query = QueryBuilders.match()
.field("name")
.query(FieldValue.of("Android smartphone"))
.build()
._toQuery();
SearchRequest request = SearchRequest.of(
b -> b.index("store-items")
.query(query)
);
SearchResponse<StoreItem> searchResponse = elasticsearchClient
.search(request, StoreItem.class);
HitsMetadata<StoreItem> hits = searchResponse.hits();
List<StoreItem> results = hits.hits().stream()
.map(Hit::source)
.collect(Collectors.toList());
assertThat(results)
.hasSize(1)
.containsExactlyInAnyOrder(androidPhone);
}
我們使用indexUsingElasticsearchClient()方法為新文件建立了索引。然後,我們建立了[SearchRequest](https://artifacts.elastic.co/javadoc/co/elastic/clients/elasticsearch-java/8.14.3/co/elastic/clients/elasticsearch/core/SearchRequest.html) ,使用 Elasticsearch Java 用戶端執行它,並將所有命中收集到StoreItem實例清單中。我們使用DSL語法來建立查詢,因此我們不必擔心序列化和反序列化。
5. 結論
正如我們所看到的,Quarkus 提供了將我們的應用程式與 Elasticsearch 整合的出色功能。首先,我們需要做的就是添加擴展依賴項並提供幾行配置。如果我們想要更多的控制,我們總是可以自己定義一個客戶端 bean。此外,在本文中,我們探討如何在 Quarkus 中使用 Elasticsearch 的低階 REST 用戶端和高階 Java 用戶端。
像往常一樣,完整的源代碼可以在 GitHub 上找到。