Jest — ElasticSearch Java 客戶端

1. 介紹

任何使用過Elasticsearch的人都知道,使用基於rest的搜索API構建查詢多是單調乏味且容易出錯的。java

在本教程中,咱們將研究Jest,一個用於Elasticsearch的HTTP Java客戶端。Elasticsearch提供了本身原生的Java客戶端,然而 Jest提供了更流暢的API和更容易使用的接口git

2. Maven 依賴

咱們須要作的第一件事是導入Jest庫到咱們的POM文件中:github

<dependency>
    <groupId>io.searchbox</groupId>
    <artifactId>jest</artifactId>
    <version>6.3.1</version>
</dependency>
複製代碼

Jest的版本是遵循Elasticsearch的主版本號的。 這將確保客戶端和服務端之間的兼容性。spring

經過包含Jest依賴項,相應的[Elasticsearch庫](search.maven.org/search?q=g:… a:elasticsearch)將被包含爲傳遞依賴項。json

3. 使用Jest Client

在本節中,咱們將研究如何使用Jest client執行Elasticsearch中的常見任務。安全

要使用Jest client,咱們只需使用 JestClientFactory 建立一個 JestClient 對象。這些對象的建立開銷很高,並且是線程安全的,所以咱們將建立一個能夠在整個應用程序中共享的單例實例:app

public JestClient jestClient() {
    JestClientFactory factory = new JestClientFactory();
    factory.setHttpClientConfig(
      new HttpClientConfig.Builder("http://localhost:9200")
        .multiThreaded(true)
        .defaultMaxTotalConnectionPerRoute(2)
        .maxTotalConnection(10)
        .build());
    return factory.getObject();
}
複製代碼

這裏將建立一個Jest client,該客戶端鏈接到本地運行的Elasticsearch。雖然這個鏈接示例很簡單,可是Jest還徹底支持代理、SSL、身份驗證,甚至節點發現異步

JestClient 類是通用類,只有少數公共方法。咱們將使用的一個主要方法是execute,它接受Action接口的一個實例。Jest客戶端提供了幾個構建器類來幫助建立與Elasticsearch交互的不一樣操做。elasticsearch

全部Jest調用的結果都是JestResult的一個實例。 咱們能夠經過調用 issucceeded 方法來檢查是否成功。對於失敗的操做,咱們能夠調用GetErrorMessage方法來獲取更多詳細信息:maven

JestResult jestResult = jestClient.execute(new Delete.Builder("1").index("employees").build());

if (jestResult.isSucceeded()) {
    System.out.println("Success!");
}
else {
    System.out.println("Error: " + jestResult.getErrorMessage());
}
複製代碼

3.1. 管理索引

檢查索引是否存在,咱們使用IndicatesExists操做:

JestResult result = jestClient.execute(new IndicesExists.Builder("employees").build())
複製代碼

建立一個索引,咱們使用CreateIndex操做:

jestClient.execute(new CreateIndex.Builder("employees").build());
複製代碼

這將建立一個具備默認設置的索引。咱們能夠在建立索引時覆蓋特定的設置:

Map<String, Object> settings = new HashMap<>();
settings.put("number_of_shards", 11);
settings.put("number_of_replicas", 2);
jestClient.execute(new CreateIndex.Builder("employees").settings(settings).build());
複製代碼

使用ModifyAliases操做建立或更改別名也很簡單:

jestClient.execute(new ModifyAliases.Builder(
  new AddAliasMapping.Builder("employees", "e").build()).build());
jestClient.execute(new ModifyAliases.Builder(
  new RemoveAliasMapping.Builder("employees", "e").build()).build());
複製代碼

3.2. 建立文檔

Jest client使用索引操做類索引或建立新文檔變得容易。Elasticsearch中的文檔只是JSON數據,有多種方法能夠將JSON數據傳遞給Jest client 進行索引。

對於這個例子,讓咱們使用一個虛構的僱員文檔:

{
    "name": "Michael Pratt",
    "title": "Java Developer",
    "skills": ["java", "spring", "elasticsearch"],
    "yearsOfService": 2
}
複製代碼

表示JSON文檔的第一種方法是使用Java字符串。雖然咱們能夠手動建立JSON字符串,但咱們必須注意正確的格式、大括號和轉義引號字符。所以,更容易的方式是使用一個JSON庫(如Jackson)來構建咱們的JSON結構,而後將其轉換爲字符串:

ObjectMapper mapper = new ObjectMapper();
JsonNode employeeJsonNode = mapper.createObjectNode()
  .put("name", "Michael Pratt")
  .put("title", "Java Developer")
  .put("yearsOfService", 2)
  .set("skills", mapper.createArrayNode()
    .add("java")
    .add("spring")
    .add("elasticsearch"));
jestClient.execute(new Index.Builder(employeeJsonNode.toString()).index("employees").build());
複製代碼

咱們還能夠使用Java Map 來表示JSON數據,並將其傳遞給索引操做:

Map<String, Object> employeeHashMap = new LinkedHashMap<>();
employeeHashMap.put("name", "Michael Pratt");
employeeHashMap.put("title", "Java Developer");
employeeHashMap.put("yearsOfService", 2);
employeeHashMap.put("skills", Arrays.asList("java", "spring", "elasticsearch"));
jestClient.execute(new Index.Builder(employeeHashMap).index("employees").build());
複製代碼

最後,Jest client 能夠接受表示要索引的文檔的任何POJO。假設咱們有一個Employee類:

public class Employee {
    String name;
    String title;
    List<String> skills;
    int yearsOfService;
}
複製代碼

咱們能夠把這個類的一個實例直接傳遞給Index builder:

Employee employee = new Employee();
employee.setName("Michael Pratt");
employee.setTitle("Java Developer");
employee.setYearsOfService(2);
employee.setSkills(Arrays.asList("java", "spring", "elasticsearch"));
jestClient.execute(new Index.Builder(employee).index("employees").build());
複製代碼

3.3. 讀取文檔

使用Jest client從Elasticsearch訪問文檔有兩種主要方法。首先,若是咱們知道文檔ID,咱們能夠使用get操做直接訪問它:

jestClient.execute(new Get.Builder("employees", "17").build());
複製代碼

要訪問返回的文檔,咱們必須調用其中一個getSource方法。咱們能夠將結果做爲原始JSON獲取,或者將其反序列化爲DTO:

Employee getResult = jestClient.execute(new Get.Builder("employees", "1").build())
    .getSourceAsObject(Employee.class);
複製代碼

訪問文檔的其餘方法是使用搜索查詢,這種方式在Jest中是經過搜索操做實現的。

Jest client 支持所有的 Elasticsearch query DSL。 與索引操做同樣,查詢被表示爲JSON文檔,而且有多種執行搜索的方法。

首先,咱們能夠傳遞一個表示搜索查詢的JSON字符串。提醒一下,咱們必須確保字符串是正確轉義的,而且是有效的JSON:

String search = "{" +
  " \"query\": {" +
  " \"bool\": {" +
  " \"must\": [" +
  " { \"match\": { \"name\": \"Michael Pratt\" }}" +
  " ]" +
  " }" +
  " }" +
  "}";
jestClient.execute(new Search.Builder(search).build());
複製代碼

與上面的索引操做同樣,咱們能夠使用Jackson之類的庫來構建JSON查詢字符串。此外,咱們還能夠使用原生的Elasticsearch查詢操做API。這樣作的一個缺點是,咱們的應用程序必須依賴於完整的Elasticsearch庫。

咱們能夠使用 getSource 方法來訪問搜索操做中匹配的文檔。然而,Jest還提供了Hit類,它包裝了匹配的文檔並提供有關結果的元數據。 使用Hit類,咱們能夠訪問每一個結果的附加元數據:得分、路由和解釋結果,舉幾個例子:

List<SearchResult.Hit<Employee, Void>> searchResults = 
  jestClient.execute(new Search.Builder(search).build())
    .getHits(Employee.class);
searchResults.forEach(hit -> {
    System.out.println(String.format("Document %s has score %s", hit.id, hit.score));
});
複製代碼

3.4. 更新文檔

Jest爲更新文檔提供了一個簡單的Update操做:

employee.setYearOfService(3);
jestClient.execute(new Update.Builder(employee).index("employees").id("1").build());
複製代碼

它接受與咱們前面看到的索引操做相同的JSON表示,這使得在兩個操做之間共享代碼變得很容易。

3.5. 刪除文檔

從索引中刪除文檔是使用Delete操做完成的。它只須要索引名和文檔ID:

jestClient.execute(new Delete.Builder("17")
  .index("employees")
  .build());
複製代碼

4. 批量操做

Jest client 一樣支持批量操做。 這意味着咱們能夠經過同時發送多個操做來節省時間和帶寬。

使用批量操做,咱們能夠將任意數量的請求組合成單個調用。咱們甚至能夠將不一樣類型的請求組合在一塊兒:

jestClient.execute(new Bulk.Builder()
  .defaultIndex("employees")
  .addAction(new Index.Builder(employeeObject1).build())
  .addAction(new Index.Builder(employeeObject2).build())
  .addAction(new Delete.Builder("17").build())
  .build());
複製代碼

5. 異步操做

Jest client 一樣支持異步操做。 這意味着咱們能夠使用非阻塞I/O執行上述任何操做。

要異步調用操做,只需使用客戶端的executeAsync方法:

jestClient.executeAsync(
  new Index.Builder(employeeObject1).build(),
  new JestResultHandler<JestResult>() {
      @Override public void completed(JestResult result) {
          // handle result
      }
      @Override public void failed(Exception ex) {
          // handle exception
      }
  });
複製代碼

注意,除了(本例中是索引)操做以外,異步流還須要一個JestResultHandler。當操做完成時,Jest client 將調用該對象。該接口有兩個方法—完成和失敗—分別容許處理操做的成功或失敗。

6. 結論

在本教程中,咱們簡要介紹了Jest client,一個用於Elasticsearch的RESTful Java客戶端。雖然咱們只介紹了它的一小部分功能,但很明顯Jest是一個健壯的Elasticsearch客戶端。它的流暢的構建器類和RESTful接口使其易於學習,而且它對Elasticsearch接口的徹底支持使其成爲原生客戶端的一個有力的替代方案。

和往常同樣,本教程中的全部代碼示例都在咱們的Github頁面上。

原文:www.baeldung.com/elasticsear…

做者:Michael Pratt

譯者:huowolf/

相關文章
相關標籤/搜索