Elasticsearch is an open, free and distributed search engine and an analytical tool built on top of Apache Lucene.
It first stores documents in an index. It uses powerful queries to search the index and runs its analytical functions on the data. Elasticsearch uses REST APIs to perform operations.
To use Elasticsearch in spring-boot, an interface is implemented as an alternative to its REST APIs. In this blog, we'll learn how to use Elasticsearch in Spring-boot.
Let's take a look using a step by step guide with an example.
.
1. Add Maven dependency
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-elasticsearch</artifactId> </dependency>
2. Connection with Elasticsearch Instance
To connect with Elasticsearch server, Spring data Elasticsearch uses JHLC(Java High Level REST Client)
@Configuration @EnableElasticsearchRepositories @ComponentScan public class ElasticsearchClientConfig extends AbstractElasticsearchConfiguration { @Override @Bean public RestHighLevelClient elasticsearchClient() { final ClientConfiguration clientConfiguration = ClientConfiguration .builder() .connectedTo("localhost:9200") .build(); return RestClients.create(clientConfiguration).rest(); } }
3. Create a document
@Document(indexName = "studentindex") public class Student { @Id private String id; private String name; private String course; private Integer semester; ... }
Here, Studentindex is the index name for Elasticsearch, provided using @Document annotation.
1. ElasticSearchRestTemplate: It is an implementation of the ElasticSearchOperations interface. Here, you can write your own queries.
2. ElasticSearchRepository Interface: ElasticSearch queries can be generated using repository's methods. It is easier and fast but problematic for writing complex queries.
1. ElasticSearchRepository for indexing and searching
We need to create a repository interface by extending ElasticSearchRepository interface.
public interface StudentRepository extends ElasticsearchRepository<Student, String> { List<Student> findByName(String name); List<Student> findByCourseContaining(String course); }
Now, StudentRepository inherits ElasticsearchRepository's methods. So, Whenever a save() or saveAll() methods invoke, data gets also inserted in index.
We can perform our searching using methods we defined in our StudentRepository.
2. ElasticSearchRestTemplate for indexing and searching
ElasticsearchRestTemplate implements the ElasticsearchOperations interface, which does the heavy lifting for low-level search and cluster actions.
This interface has the method index() for adding a single document and bulkIndex() for adding multiple documents to the index. Here i'm using index() method in this example.
@Service public class StudentSearchService { private ElasticsearchOperations elasticsearchOperations; private static final String STUDENT_INDEX = "studentindex"; public String createStudentIndex(Student student) { IndexQuery indexQuery = new IndexQueryBuilder() .withId(student.getId().toString()) .withObject(student).build(); String documentId = elasticsearchOperations .index(indexQuery, IndexCoordinates.of(STUDENT_INDEX)); return documentId; } }
now, to search documents, ElasticsearchRestTemplate has a search() method
@Service public class StudentSearchService { private ElasticsearchOperations elasticsearchOperations; private static final String STUDENT_INDEX = "studentindex"; public void findStudentsByCourse(final String course) { QueryBuilder queryBuilder = QueryBuilders .matchQuery("course", course); Query searchQuery = new NativeSearchQueryBuilder() .withQuery(queryBuilder) .build(); SearchHits<Student> studentHits = elasticsearchOperations .search(searchQuery, Student.class, IndexCoordinates.of(STUDENT_INDEX)); } }