Jest - Pelanggan Java Elasticsearch

1. Pengenalan

Sesiapa yang pernah bekerjasama dengan Elasticsearch tahu bahawa membina pertanyaan menggunakan API carian RESTful mereka boleh membosankan dan terdedah kepada kesalahan.

Dalam tutorial ini, kita akan melihat Jest, klien HTTP Java untuk Elasticsearch. Walaupun Elasticsearch menyediakan klien Java sendiri, Jest menyediakan API yang lebih lancar dan antara muka yang lebih mudah untuk digunakan .

2. Ketergantungan Maven

Perkara pertama yang perlu kita lakukan ialah mengimport perpustakaan Jest ke dalam POM kami:

 io.searchbox jest 6.3.1 

Versi untuk Jest mengikuti produk Elasticsearch utama . Ini membantu memastikan keserasian antara pelanggan dan pelayan.

Dengan memasukkan ketergantungan Jest, perpustakaan Elasticsearch yang sesuai akan dimasukkan sebagai pergantungan transitif.

3. Menggunakan Jest Client

Di bahagian ini, kita akan melihat penggunaan klien Jest untuk melakukan tugas biasa dengan Elasticsearch.

Untuk menggunakan klien Jest, kami hanya membuat objek JestClient menggunakan JestClientFactory . Objek-objek ini mahal untuk dibuat dan tidak selamat pada benang , jadi kami akan membuat satu contoh yang dapat dikongsi di 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 yang disambungkan ke klien Elasticsearch yang berjalan di dalam negara. Walaupun contoh sambungan ini remeh, Jest juga mempunyai sokongan penuh untuk proksi, SSL, pengesahan, dan penemuan nod .

The JestClient kelas adalah generik dan hanya mempunyai segelintir kaedah awam. Yang utama yang akan kami gunakan adalah melaksanakan , yang mengambil contoh antara muka Tindakan . Pelanggan Jest menyediakan beberapa kelas pembina untuk membantu membuat tindakan yang berbeza yang berinteraksi dengan Elasticsearch.

Hasil dari semua panggilan Jest adalah contoh JestResult . Kita dapat memeriksa kejayaan dengan memanggil isSucceeded . Untuk tindakan yang tidak berjaya, kita boleh memanggil getErrorMessage untuk mendapatkan lebih banyak maklumat:

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

Untuk memeriksa sama ada indeks ada, 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 tetapan lalai. Kita boleh mengatasi tetapan tertentu semasa 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 menukar alias juga mudah dengan 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

Pelanggan Jest memudahkan mengindeks - atau membuat - dokumen baru menggunakan kelas tindakan Indeks . Dokumen di Elasticsearch hanyalah data JSON , dan terdapat banyak cara untuk menyampaikan data JSON kepada klien Jest untuk diindeks.

Untuk contoh ini, mari gunakan dokumen Pekerja khayalan:

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

Cara pertama untuk mewakili dokumen JSON adalah dengan menggunakan Java String . Walaupun kita dapat membuat rentetan JSON secara manual, kita harus berhati-hati dengan pemformatan, pendakap, dan karakter kutipan yang terlepas.

Oleh itu, lebih mudah menggunakan perpustakaan JSON seperti Jackson untuk membina struktur JSON kami dan kemudian menukar ke 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 mewakili data JSON dan menyebarkannya 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, pelanggan Jest dapat menerima sebarang POJO yang mewakili dokumen yang akan diindeks. Katakan kita mempunyai kelas Pekerja :

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

Kita boleh menyampaikan contoh kelas ini terus ke pembangun 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

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

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

Untuk mengakses dokumen yang dikembalikan, kita mesti memanggil salah satu daripada pelbagai kaedah getSource . Kita boleh mendapatkan hasilnya sebagai JSON mentah atau menghapuskannya kembali ke DTO:

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

Cara lain untuk mengakses dokumen adalah menggunakan pertanyaan carian, yang dilaksanakan di Jest dengan tindakan Carian .

Pelanggan Jest menyokong DSL pertanyaan Elasticsearch sepenuhnya . Sama seperti operasi pengindeksan, pertanyaan dinyatakan sebagai dokumen JSON, dan terdapat banyak cara untuk melakukan carian.

Pertama, kita dapat meneruskan rentetan JSON yang mewakili pertanyaan carian. Sebagai peringatan, kita mesti berhati-hati untuk memastikan tali itu terlepas dengan betul dan sah JSON:

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

Seperti tindakan Indeks di atas, kami dapat menggunakan perpustakaan seperti Jackson untuk membina rentetan pertanyaan JSON kami.

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.

Walaupun kami hanya merangkumi sebahagian kecil fungsinya, jelas bahawa Jest adalah pelanggan Elasticsearch yang kuat. Kelas pembangunnya yang lancar dan antara muka RESTful menjadikannya senang dipelajari, dan sokongan penuhnya untuk antaramuka Elasticsearch menjadikannya alternatif yang mampu untuk pelanggan asli.

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