Spring Data Elasticsearch - Querying



Since Spring Data ElasticSearch repository works on top of PagingAndSortingRepository. It allows both type of query, i.e., Standard query methods as well as customer query methods. Lets work with both one by one.

Query Methods

Query methods are also called as method name based queries. It allows us to look for the data based on the fields methods name. Lets suppose we want to find the Customer from Elasticsearch based on his name. To do so we can add below Query method to our repository.

Page<Customer> findByName(String name, Pageable pageable);

Custom QueryMethods

There may be a situation where we couldnt fetch the data from Elasticsearch based on the Query methods, In that case we can use custom queries. Lets say we want to fetch the customer details based on his City name, where city is the part of Address and Address is nested in Customer class as list. No worry it too simple. In this case we will use @Query annotation from org.springframework.data.elasticsearch.annotations over our custom query.

@Query("{\"bool\": {\"must\": [{\"match\": {\"addresses.city\": \"?0\"}}]}}")
Page<Customer> findByAddressCityUsingCustomQuery(String name, Pageable pageable);

Above query returns the customer having city equivalent to passed city in the parameter.

Hands on Coding for Query/Custom Query Methods

Lets add above two methods in our repository. Now our repository will look like −

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.annotations.Query;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;
import com.tutorialspoint.es.document.Customer;
@Repository
public interface CustomerRepository extends ElasticsearchRepository<Customer, Long> {
   Page<Customer> findByName(String name, Pageable pageable);
   @Query("{\"bool\": {\"must\": [{\"match\": {\"addresses.city\": \"?0\"}}]}}")
   Page<Customer> findByAddressCityUsingCustomQuery(String name, Pageable pageable);
}

Lets write create some end point to fetch out these two operations. Add below two end points in the controller.

// Retrieving a customer from ElasticSearch by Name
@GetMapping("/customer/find-by-name/{name}")
public List<Customer> fetchCustomerByNAme(@PathVariable String name) {
   Page<Customer> customerOpt = customerService.findByName(name);
   return customerOpt.get().collect(Collectors.toList());
}
// Retrieving a customer from ElasticSearch by City name
@GetMapping("/customer/find-by-address-city/{city}")
public List<Customer> fetchCustomerByCity(@PathVariable String city) {
   Page<Customer> customerOpt = customerService.findByAddressCity(city);
   return customerOpt.get().collect(Collectors.toList());
}

Lets add below two methods to our services,

@Override
public Page<Customer> findByName(String name) {
   return customerRepository.findByName(name, PageRequest.of(0, 2));
}
@Override
public Page<Customer> findByAddressCity(String city) {
   return customerRepository.findByAddressCityUsingCustomQuery(city, PageRequest.of(0, 2));
}

Lets perform below two GET operation for fetching customer based on his name and based on city name.

GET API http://localhost:8080/rest/customer/find-by-name/Jack

RESPONSE

[
   {
      "id": 1,
      "name": "Jack",
      "email": "jack@yahoo.com",
      "salary": 18100.0,
      "addresses": [
         {
            "city": "Mumbai",
            "country": "India",
            "zipCode": 111111
         }
      ]
   }
]

GET API http://localhost:8080/rest/customer/find-by-address-city/Mumbai

RESPONSE

[
   {
      "id": 1,
      "name": "Jack",
      "email": "jack@yahoo.com",
      "salary": 18100.0,
      "addresses": [
         {
            "city": "Mumbai",
            "country": "India",
            "zipCode": 111111
         }
      ]
   }
]

We will learn more about fetching complex data from elastic search in next section

Advertisements