Elasticsearch in Action: Indexing and Searching using Java API Client (2/2)

Madhusudhan Konda
3 min readJan 10, 2023
Elasticsearch in Action by M Konda

The excerpts are taken from my book Elasticsearch in Action, Second Edition. The code is available in my GitHub repository. You can find executable Kibana scripts in the repository so you can run the commands in Kibana straight away. All code is tested against Elasticsearch 8.4 version.

Part 2 of the Java API client mini-series.

  1. Introducing Java API client: Creating an index
  2. Search and index using Java API client

In the last article, we learned how to instantiate the Java API client. In this instalment, we will use the client to index and search data.

We know how to index a document using query DSL in the Kibana console (or using cURL). For example the code in the following listing will index a flight with a random ID as the primary key:

POST flights/_doc
{
"route":"London to New York",
"name":"BA123",
"airline":"British Airways",
"duration_hours":5
}

Let’s index the same document but this time using the Java API client. Remember, we already created the flights index in the previous section, so all we need to do is use the fluent API to build the query. The listing below demonstrates this query:

public void indexDocument(String indexName, Flight flight) throws IOException {
IndexResponse indexResponse = this.elasticsearchClient.index(
i -> i.index(indexName)
.document(flight)
);
System.out.println("Document indexed"+indexResponse);
}

Executing this query will index a flight into our flights index. The elasticsearchClient exposes an index method that can be chained up with other methods such as id and document. In the above case, we didn’t use the ID as we’ve let the system generate it for us.

The document method expects the flight object; did you notice we didn’t do any transformation of the flight Java object to JSON? That’s because, we’ve delegated the responsibility of marshaling and unmarshaling to the JacsonJasonpMapper class that we associated with the transport object earlier on.

Let’s jump on to writing a query to search for a flight.

Searching

Searching data using queries with Java API client follows the similar path — invoking search method in the ElasticsearchClient class by passing the required query. There’s one subtle difference though — unlike the other features exposing a client per namespace, the search feature does not. That is, there’s no separate “client” per se, unlike ElasticsearchIndicesClient.

Let’s just say we wish to search for a route from London to New York: We create a match query providing the “London New York” as the search criteria against the route field in a nicely formed DSL when working with Kibana. This is demonstrated in the listing below:

this.elasticsearchClient.search(searchRequest -> searchRequest
.index(indexName)
.query(queryBuilder ->
queryBuilder.match(matchQBuilder->
matchQBuilder.field("route")
.query(searchText))),Flight.class
);

The search method is expecting a search request, it is provided as a lambda expression to the method as you see above. The query will be written using another lambda function — given a query request (Query.Builder object), invoke the match function with the MatchQuery.Builder object. The JSON will be converted to a Flight Java object, which is why Flight.class is provided as the argument to the query method.

The response from the search method is a SearchResponse — so we can capture the results as shown in the snippet below:

SearchResponse searchResponse =   
this.elasticsearchClient.search(..)

The searchResponse consists of results as hits — which can be iterated through to get to the list of Flights that were returned. The following listing shows the rest of the search request including the Flights returned in the response:

// Capture flights
List<Flight> flights =
(List<Flight>) searchResponse.hits().hits()
.stream().collect(Collectors.toList());

// Or print them to the console
searchResponse.hits().hits()
.stream().forEach(System.out::println);

As you can infer, the searchResponse object has the results in the hits array — all we need to make sure is to cast the hits to appropriate domain objects (Flight in this case). Full source code of this example is available on my GitHub page here:https://github.com/madhusudhankonda/elasticsearch-clients

This is part 2 of 2 part min-series of Java client for Elasticsearch:

  1. Introducing Java API client: Creating an index
  2. Search and index using Java API client

That’s pretty much about Java API client.

--

--

Madhusudhan Konda

Madhusudhan Konda is a full-stack lead engineer, mentor, and conference speaker. He delivers live online training on Elasticsearch, Elastic Stack &Spring Cloud