Jest - Klien Java Elasticsearch

1. Perkenalan

Siapa pun yang pernah bekerja dengan Elasticsearch tahu bahwa membuat kueri menggunakan API penelusuran RESTful mereka bisa membosankan dan rawan kesalahan.

Dalam tutorial ini, kita akan melihat Jest, klien HTTP Java untuk Elasticsearch. Sementara Elasticsearch menyediakan klien Java aslinya sendiri, Jest menyediakan API yang lebih lancar dan antarmuka yang lebih mudah untuk digunakan .

2. Ketergantungan Maven

Hal pertama yang perlu kita lakukan adalah mengimpor perpustakaan Jest ke POM kita:

 io.searchbox jest 6.3.1 

Pembuatan versi untuk Jest mengikuti versi produk utama Elasticsearch . Ini membantu memastikan kompatibilitas antara klien dan server.

Dengan menyertakan dependensi Jest, library Elasticsearch terkait akan disertakan sebagai dependensi transitif.

3. Menggunakan Jest Client

Di bagian ini, kita akan melihat penggunaan klien Jest untuk melakukan tugas-tugas umum dengan Elasticsearch.

Untuk menggunakan klien Jest, kita cukup membuat objek JestClient menggunakan JestClientFactory . Objek-objek ini mahal untuk dibuat dan aman untuk thread , jadi kami akan membuat instance tunggal yang dapat dibagikan ke seluruh aplikasi kami:

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

Ini akan membuat klien Jest terhubung ke klien Elasticsearch yang berjalan secara lokal. Meskipun contoh koneksi ini sepele, Jest juga memiliki dukungan penuh untuk proxy, SSL, otentikasi, dan bahkan penemuan node .

Kelas JestClient bersifat umum dan hanya memiliki beberapa metode publik. Yang utama yang akan kita gunakan adalah mengeksekusi , yang mengambil contoh dari antarmuka Action . Klien Jest menyediakan beberapa kelas pembangun untuk membantu membuat tindakan berbeda yang berinteraksi dengan Elasticsearch.

Hasil dari semua panggilan Jest adalah turunan dari JestResult . Kami dapat memeriksa keberhasilan dengan memanggil isSucceeded . Untuk tindakan yang tidak berhasil, kita dapat memanggil getErrorMessage untuk mendapatkan detail selengkapnya:

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. Mengelola Indeks

Untuk memeriksa apakah ada indeks, kami menggunakan tindakan IndicesExists :

JestResult result = jestClient.execute(new IndicesExists.Builder("employees").build()) 

Untuk membuat indeks, kami menggunakan tindakan CreateIndex :

jestClient.execute(new CreateIndex.Builder("employees").build());

Ini akan membuat indeks dengan pengaturan default. Kami dapat mengganti pengaturan tertentu selama pembuatan indeks:

Map settings = new HashMap(); settings.put("number_of_shards", 11); settings.put("number_of_replicas", 2); jestClient.execute(new CreateIndex.Builder("employees").settings(settings).build());

Dan membuat atau mengubah alias juga mudah menggunakan tindakan 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. Membuat Dokumen

Klien Jest membuatnya mudah untuk mengindeks - atau membuat - dokumen baru menggunakan kelas tindakan Indeks . Dokumen di Elasticsearch hanyalah data JSON , dan ada banyak cara untuk meneruskan data JSON ke klien Jest untuk diindeks.

Untuk contoh ini, mari gunakan dokumen rekaan Karyawan:

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

Cara pertama untuk merepresentasikan dokumen JSON adalah dengan menggunakan String Java . Meskipun kita dapat membuat string JSON secara manual, kita harus memperhatikan pemformatan yang tepat, tanda kurung kurawal, dan karakter kutipan yang keluar.

Oleh karena itu, lebih mudah menggunakan pustaka JSON seperti Jackson untuk membangun struktur JSON kita dan kemudian mengonversinya menjadi String :

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());

Kita juga dapat menggunakan Peta Java untuk merepresentasikan data JSON dan meneruskannya ke tindakan Indeks :

Map 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());

Akhirnya, klien Jest dapat menerima POJO apa pun yang mewakili dokumen yang akan diindeks. Katakanlah kita memiliki kelas Karyawan :

public class Employee { String name; String title; List skills; int yearsOfService; }

Kita bisa meneruskan instance kelas ini langsung ke pembuat Indeks :

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. Membaca Dokumen

Ada dua cara utama untuk mengakses dokumen dari Elasticsearch menggunakan klien Jest. Pertama, jika kita mengetahui ID dokumennya, kita dapat mengaksesnya secara langsung menggunakan tindakan Get :

jestClient.execute(new Get.Builder("employees", "17").build());

Untuk mengakses dokumen yang dikembalikan, kita harus memanggil salah satu dari berbagai metode getSource . Kita bisa mendapatkan hasilnya sebagai JSON mentah atau deserialisasinya kembali ke DTO:

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

Cara lain untuk mengakses dokumen menggunakan permintaan pencarian, yang diimplementasikan dalam Jest dengan tindakan Pencarian .

Klien Jest mendukung DSL kueri Elasticsearch lengkap . Sama seperti operasi pengindeksan, kueri diekspresikan sebagai dokumen JSON, dan ada beberapa cara untuk melakukan penelusuran.

Pertama, kita bisa mengirimkan string JSON yang mewakili kueri penelusuran. Sebagai pengingat, kita harus berhati-hati untuk memastikan string tersebut lolos dengan benar dan merupakan JSON yang valid:

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

Seperti tindakan Indeks di atas, kita bisa menggunakan pustaka seperti Jackson untuk membangun string kueri JSON kita.

Additionally, we can also use the native Elasticsearch query action API. The one downside of this is that our application has to depend on the full Elasticsearch library.

With the Search action, the matching documents can be accessed using the getSource methods. However, Jest also provides the Hit class, which wraps the matching documents and provides metadata about the results. Using the Hit class, we can access additional metadata for each result: score, routing, and explain results, to name a few:

List
    
      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. Updating Documents

Jest provides a simple Update action for updating documents:

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

It accepts the same JSON representations as the Index action we saw earlier, making it easy to share code between the two operations.

3.5. Deleting Documents

Deleting a document from an index is done using the Delete action. It only requires an index name and document ID:

jestClient.execute(new Delete.Builder("17") .index("employees") .build());

4. Bulk Operations

Jest client also supports bulk operations. This means we can save time and bandwidth by sending multiple operations together at the same time.

Using the Bulk action, we can combine any number of requests into a single call. We can even combine different types of requests together:

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. Asynchronous Operations

Jest client also supports asynchronous operations, which means we can perform any of the above operations using non-blocking I/O.

To invoke an operation asynchronously, simply use the executeAsync method of the client:

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

Note that in addition to the action (indexing in this case), the asynchronous flow also requires a JestResultHandler. The Jest client will call this object when the action has finished. The interface has two methods – completed and failed – that allow handling either success or failure of the operation, respectively.

6. Conclusion

In this tutorial, we have looked briefly at the Jest client, a RESTful Java client for Elasticsearch.

Meskipun kami hanya membahas sebagian kecil dari fungsinya, jelas bahwa Jest adalah klien Elasticsearch yang tangguh. Kelas pembangunnya yang lancar dan antarmuka RESTful membuatnya mudah dipelajari, dan dukungan penuhnya untuk antarmuka Elasticsearch menjadikannya alternatif yang mampu untuk klien asli.

Seperti biasa, semua contoh kode dalam tutorial berakhir di GitHub.