preloader

A quick guide to Elasticsearch Java clients [Part 1]

This is the first part of three parts series, where we are going to explore a simple way to configure and quickly get started working with Elasticsearch, with the main focus on going over available Java clients, and examine their advantages and drawbacks based on features available and potential use cases and needs.

In this part, we are going to focus on the Jest Java client, but before that, we are just briefly going to go over the installation and running local server instance in the next chapter.

Quick guide to Elasticsearch Java clients [Part 1]

Elasticsearch setup

We are not going to deep dive into the inner workings of Elasticsearch itself, for that purpose, there is official documentation.

For the purposes of this example, we are going to install a local instance of the Elasticsearch server. To do that, we have a few options. We can go to the official downloads page, download the zip/tar package and run an appropriate script file, depending on the host OS. If we have Docker installed, another option is to pull docker image and run Elasticsearch container, e.g.:

docker run -d -p 9200:9200 -p 9300:9300 –name es -e “discovery.type=single-node” -e “http.cors.enabled=true” -e “http.cors.allow-origin=*” docker.elastic.co/
elasticsearch/elasticsearch:6.2.2

 In either case, if startup went fine, after issuing GET request in your favorite browser on https://localhost:9200 URL, the response should look something like this:

{
“name” : “b3ZfQOl”,   “cluster_name” : “docker-cluster”,
“cluster_uuid” : “yPTKgWIhRaiUBrgTmciELQ”,
“version” : {
“number” : “6.2.2”,
“build _hash” : “10b1edd”,
“build_date” : “2018-02-16T19:01:30.685723Z”,
“build_snapshot” : false,
“lucene_version” : “7.2.1”,
“minimum_wire_compatibility_version” : “5.6.0”,
“minimum_index_compatibility_version” : “5.0.0”
},
“tagline” : “You Know, for Search”
}

 Notice three environment variables passed to the container: discovery.type=single-node, http.cors.enabled=true and http.cors.allow-origin=*. The first setting tells Elasticsearch server to run as a standalone node and to elect itself as master and not to join any clusters. This is sufficient for our example and most testing purposes. The second parameter enables or disables cross-origin resource sharing, i.e. whether a request from another origin can be executed against Elasticsearch. And third should only be used for testing purposes, to allow all origins. Setting up latter two parameters as shown, enables us to use elastic search head , which is a handy little tool to monitor nodes and shards, and query Elasticsearch indices.

JEST

Jest is a lightweight Java client, both in terms of jar size and memory consumption. It implements Elasticsearch REST API using Apache HttpComponents library.

To use Jest in your project add the following dependency in pom.xml for Maven:

<dependency>
<groupId>io.searchbox</groupstId>
<artifactId>jest</artifactId>
<version>5.3.3</version>
</dependency>

Or for Gradle projects in your build.gradle:

compile(‘io.searchbox:jest:5.3.3’)

Configuring Jest client is easy, for e.g.:

final JestClientFactory factory = new JestClientFactory();
factory.setHttpClientConfig(new HttpClientConfig
.Builder(“127.0.0.1”)
.multiThreaded(true)
.build());
return factory.getObject();

Besides being lightweight, other really nice feature that Jest provides is using Java Beans directly for indexing and searching. For example, if we have POJO named Comment, it could be indexed in following manner:

Builder bulkIndexBuilder = new Bulk.Builder();
comments.stream().forEach(c → bulkIndexBuilder.addAction(new Index.Builder(c).index(“comment”).
type(“comment”).build()));
client.execute(bulkIndexBuilder
.build());

And then query it, and retrieving all hits:

List<Hit<Comment, Void>> hits = result.getHits(Comment .class);

If we want more sophisticated search, we really have two options available. First is to build string query directly, like so:

String query = “{“match” : {“message” : “Test it”}}”;

We could see how this way of building search queries can be hard for more complex examples. This option is also not flexible, extensible and fairly hard to maintain in the long run.

Another option is to include Elasticsearch dependency on the classpath and to use its query builders. It gives cleaner, more flexible and maintainable code, but we are losing on the lightweight side of the things.

Summary

Overall, Jest offers a fairly good range of functionalities in lightweight packaging, and in combination with Elasticsearch dependency on the classpath can be considered for a wide range of use cases.

In the next part of the series, we are going to explore Spring data elasticsearch client.

Links and references:

About the author:

Dragan Torbica is a Software Engineer with 7 years of experience mostly in Java and Spring. He believes that software is not something that can be manufactured nor can it be delivered faster by merely adding more lines of code and that writing good software requires skill and careful attention. Currently, he’s working for BrightMarbles.io as Senior Software Developer and Technical Team Lead.