Elasticsearch: Query using Java High Level Rest Client

Image by Gerd Altmann from Pixabay

In the previous post we saw how to configure Elasticsearch Java high level rest client. In this post we are going to discuss how to make search request using the same.

Introduction

Once we have configured our Elasticsearch Java high level rest client, it won't be useful if we don't make it work. Here we are going to use it to make some queries and see the result. We will use some fake data here.

Adding Data

We can download data from Elasticsearch repository. If you are using Linux the we can download the data as shown  below:

wget https://github.com/elastic/elasticsearch/blob/master/docs/src/test/resources/accounts.json?raw=true -O accounts.json     

Once downloaded, run the below commands to insert data into Elasticsearch 

# Create an index named "accounts"
curl XPUT http://localhost:9200/accounts
# Bulk insert data into this index
curl -s -H "Content-Type: application/x-ndjson" -XPOST http://localhost:9200/accounts/_bulk --data-binary @accounts.json
# once this is done we can verify the data
curl -XGET http://localhost:9200/accounts/_count
#this should return something like this  
{"count":1000,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0}}

Query Preparation and Execution

With the data in place we want to know the followings:

  • How many users have balance between 1000-2000?

First let's see the JSON query for the same:

POST accounts/_search
{"size":10000,"query":{"bool":{"filter":[{"range":{"balance":{"gte":1000,"lte":2000}}}]}},"sort":[{"balance":{"order":"desc"}}]}

Now, we will create the same query using Elasticsearch high level rest client.

//First we need a bool query with a range filter
final var boolQueryBuilder = QueryBuilders.boolQuery();
    boolQueryBuilder
        .filter(QueryBuilders.rangeQuery("balance")
                .gte(1000).lte(2000)
                .includeLower(true)
                .includeUpper(false));

//After this we provide this to SearchSourceBuilder
final var searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.size(1000);
searchSourceBuilder.query(boolQueryBuilder);
searchSourceBuilder.sort("balance");

//And pass this source  builder to search request
final var searchRequest = new SearchRequest();
searchRequest.indices("accounts");
searchRequest.source(searchSourceBuilder);

Once that's done, we need to use the HighLevelRestClient to call Elasticsearch

final ElasticsearchConfig elasticsearchConfig = new ElasticsearchConfig();
final RestHighLevelClient restHighLevelClient = elasticsearchConfig.restHighLevelClient();
final var searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

After this we can parse the result as shown below:

final var hits = searchResponse.getHits().getHits();
final var customers = Arrays.stream(hits)
        .map(SearchHit::getSourceAsMap)
        // Here we are mapping the data to string. you can also map to some object like Account
        .map(stringObjectMap -> "Name: " + stringObjectMap.get("firstname") + " "
            + stringObjectMap.get("lastname") + ", Balance: " + stringObjectMap.get("balance"))
        .collect(Collectors.toList());

A working code example is present in this git repository.

References

  • https://github.com/elastic/elasticsearch/blob/master/docs/src/test/resources/accounts.json
  • https://pixabay.com/users/geralt-9301/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=1248053
  • https://qbox.io/blog/understanding-bulk-indexing-in-elasticsearch/
  • https://pixabay.com/illustrations/hand-magnifying-glass-earth-globe-1248053/

Comments