Spring Boot Elasticsearch

Spring Data has a starter for Elasticsearch that takes away the boilerplate code of configuring Elasticsearch to work with Spring.

First create a springboot application.

Include this dependency to import Elasticsearch dependencies.



Configure Elasticsearch.

You can change the host url(localhost:9200) to point to your respective environment like dev, qa, or production when needed.
Make sure to use @EnableElasticsearchRepositories on the configuration class. Also it is important to specify the package where your Elasticsearch repositories are in. Springboot needs to know that so that it cans and configures those repositories and their indexes.

@EnableElasticsearchRepositories(basePackages = "com.lovemesomecoding.es.repository")
public class ElasticsearchConfig {

    public RestHighLevelClient client() {
        ClientConfiguration clientConfiguration = ClientConfiguration.builder().connectedTo("localhost:9200").build();
        return RestClients.create(clientConfiguration).rest();

    public ElasticsearchOperations elasticsearchTemplate() {
        return new ElasticsearchRestTemplate(client());


Create your index repository using ElasticsearchRepository.

package com.lovemesomecoding.es.repository;

import java.util.List;

import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

import com.lovemesomecoding.es.user.User;

public interface UserRepository extends ElasticsearchRepository<User, Long> {

    List<User> findByLastName(String lastName);


Create your index

I prefer using Spring Data annotations to create and manage my index. This allows Spring Data to manage index mapping, field type, etc which is time consuming I were to do it myself. When your application boots up it will automatically create or update your index and its mapping based on your Index class. Without this you would have to manually create/update index when there are new fields to add.

@JsonInclude(value = Include.NON_NULL)
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
@Document(indexName = "sb_with_es_user")
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    private String            id;

    @MultiField(mainField = @Field(type = FieldType.Keyword), otherFields = {@InnerField(suffix = "token", type = FieldType.Text)})
    private String            firstName;

    @MultiField(mainField = @Field(type = FieldType.Keyword), otherFields = {@InnerField(suffix = "token", type = FieldType.Text)})
    private String            lastName;

    @Field(type = FieldType.Keyword)
    private String            middleName;

    @MultiField(mainField = @Field(type = FieldType.Keyword), otherFields = {@InnerField(suffix = "token", type = FieldType.Text)})
    private String            email;


Create your DAO(Data Access Object).

It is best practice to have a DAO per index so that you can isolate changes and your code is readable. Having a DAO allows you to wire in your repository(UserRepository) and RestHighLevelClient. With your repository you can take advantage of what Spring Data has developed for you to use. You also has RestHighLevelClient that you can use as a pure java client to query Elasticsearch.

public class UserDAOImp implements UserDAO {

    private UserRepository      userRepository;

    private RestHighLevelClient restHighLevelClient;

    public List<User> getAllUsers() {

        return null;

    public List<User> getUsersByFirstName(String firstName) {
        int pageNumber = 0;
        int pageSize = 10;

        SearchRequest searchRequest = new SearchRequest("sb_with_es_user");

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.from(pageNumber * pageSize);
        searchSourceBuilder.timeout(new org.elasticsearch.core.TimeValue(60, TimeUnit.SECONDS));

         * fetch only a few fields
        // searchSourceBuilder.fetchSource(new String[]{ "id", "firstName", "lastName", "cards" }, new String[]{""});

         * Query

         * Filter<br>
         * term query looks for exact match. Use keyword

        searchSourceBuilder.query(QueryBuilders.termQuery("firstName", firstName));



        if (searchSourceBuilder.sorts() != null && searchSourceBuilder.sorts().size() > 0) {
            log.info("\n{\n\"query\":{}, \"sort\":{}\n}", searchSourceBuilder.query().toString(), searchSourceBuilder.sorts().toString());
        } else {
            log.info("\n{\n\"query\":{}\n}", searchSourceBuilder.query().toString());
        List<User> users = null;
        try {
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

            log.info("isTimedOut={}, totalShards={}, totalHits={}", searchResponse.isTimedOut(), searchResponse.getTotalShards(), searchResponse.getHits().getTotalHits().value);

            users = getResponseResult(searchResponse.getHits());


        } catch (IOException e) {
            // TODO Auto-generated catch block
        return users;

    private List<User> getResponseResult(SearchHits searchHits) {

        Iterator<SearchHit> it = searchHits.iterator();

        List<User> searchResults = new ArrayList<>();

        while (it.hasNext()) {
            SearchHit searchHit = it.next();
            // log.info("sourceAsString={}", searchHit.getSourceAsString());
            try {

                User obj = ObjectUtils.getObjectMapper().readValue(searchHit.getSourceAsString(), new TypeReference<User>() {});
                // log.info("obj={}", ObjectUtils.toJson(obj));

            } catch (IOException e) {
                log.warn("IOException, msg={}", e.getLocalizedMessage());

        return searchResults;


    public List<User> getUsersByLastName(String lastName) {
        return userRepository.findByLastName(lastName);



Source code on Github

Official Documentation

Subscribe To Our Newsletter
You will receive our latest post and tutorial.
Thank you for subscribing!


Leave a Reply

Your email address will not be published. Required fields are marked *