Spring Data Solr Pagination Example

In this article of the Spring Data Solr Pagination, we will discuss how to paginate Solr query results in the spring application. Spring Data provides PageRequest class which extends AbstractPageRequest and this abstract class implements the Pageable interface. We can query to fetch Solr results in pagination by using PageRequest class from the service layer.

Using Spring Data Solr Pagination

Spring Data provides a generic way of pagination implementation in the spring application for all Spring Data implementation such as Spring Data Solr, Spring Data Cassandra, Spring Data JPA etc. But in this article, we will look into pagination implementation by using the Spring Data Solr.

Spring Data Solr Pagination Example

Creating PageRequest object for pagination

Since Spring Data 2.0, creating a new PageRequest object using constructors is deprecated. Instead of the PageRequest constructor, we can use of() static method as a factory method to create a PageRequest object. In a PageRequest object, pages are zero indexed, thus providing 0 for a page will return the first page.

We can create the PageRequest objects by using several provided overloaded version of the of() method. This object fulfils the pagination requirements as following:

Requirement 1

If you want to create a PageRequest object to specify a query results belonging to a single page. Then we have to create the PageRequest object as the following code snippet:

public static PageRequest of(int page, int size) {
     //implementation
}

//In-service class get the query results belonging to the first page when page size is 10.
PageRequest.of(0, 10)

Requirement 2

Another way, if you want to create a PageRequest object to specify the results belonging to a single page but the query results are sorted by using the value of a single field, we have discussed about Spring Data Solr Sorting in the previous article. Let’s see the following code snippet to create PageRequest object:

public static PageRequest of(int page, int size, Sort sort) {
     //implementation
}

//In-service class get the query results belonging to the first page when page size is 10.
//Query results are sorted in descending order by using a price field.
PageRequest.of(0, 10 Sort.Direction.DESC, "price")

Requirement 3

In this requirement, if you want to create a PageRequest object to specify the query results belonging to a single page but the query results are sorted by using multiple fields and sort order of different fields is same. Let’s see the following code snippet to create PageRequest object:

public static PageRequest of(int page, int size, Direction direction, String... properties) {
     //implementation
}

//In-service class get the query results belonging to the first page when page size is 10.
//Query results are sorted in descending order by using oid and odesc fields.
PageRequest.of(0, 10 Sort.Direction.DESC, "oid", "odesc")

Requirement 4

This requirement is very suitable when we want to create a PageRequest object to specify the query results belonging to a single page when the query results are sorted by using multiple fields and the sort order of different fields is not same. Let’s see the following code snippet to create PageRequest object:

public static PageRequest of(int page, int size, Direction direction, String... properties) {
     //implementation
}

//In-service class get the query results belonging to the first page when page size is 10.
//Query results are sorted in descending order by using oid field and ascending order by using odesc field.
Sort sort = Sort.by(Sort.Direction.DESC, "oid").and(Sort.by(Sort.Direction.ASC, "odesc"))
PageRequest.of(0, 10, sort)

We have discussed how to create a new PageRequest object using several flavours of the of() method of PageRequest class. The Solr query with the Pageable object return the results with following return types.

A return type of a Paginated Solr Query

In the Spring Data Solr. if you use a query method with pagination, it can have query result into two types. Let’s see these return types of the paginated query method.

  • Page<Order>: If you want pagination metadata along with query result then you have to use this return type. Here the Page is an interface of the Spring Data module and it declares the methods used to fetch pagination metadata in the application.
  • List<Order>: If you want the only content of results of the paginated Solr query then you have to use this return type

Let’s see an example of a Spring Data repository with the pagination implementation.

Spring Data Solr Repository Example

In the following repository interface, we have created a repository interface with query generation from the query method.

Query Generation From Method Name

In this step, we will explain how to create a query from the method name strategy. Let’s see the following code:

package com.doj.app.repository;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.solr.repository.SolrCrudRepository;

import com.doj.app.pojo.Order;

/**
 * @author Dinesh.Rajput
 *
 */
public interface SolrOrderRepository extends SolrCrudRepository<Order, Long> {
	
    Page<Order> findByOrderDescription(String searchTerm, Pageable pageable);
    
}

In the above code, we have created an interface SolrOrderRepository, and we have to add a Pageable parameter to the findByOrderDescription() method of this interface. Let’s see sorting using @Query annotation as the following code:

Using @Query Annotation

Here we create a method annotated with the @Query annotation. Let’s see the following code:

package com.doj.app.repository;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.solr.repository.Query;
import org.springframework.data.solr.repository.SolrCrudRepository;

import com.doj.app.pojo.Order;

/**
 * @author Dinesh.Rajput
 *
 */
public interface SolrOrderRepository extends SolrCrudRepository<Order, Long> {
    
    @Query("odesc:*?0*") 	
    Page<Order> findByOrderDescription(String searchTerm, Pageable pageable);
    
}

In the above code, we have created a method annotated with the @Query annotation. And we have also added a Pageable parameter to the findByOrderDescription() method of the SolrOrderRepository interface.

Named Queries

Let’s see the named queries method.

package com.doj.app.repository;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.solr.repository.Query;
import org.springframework.data.solr.repository.SolrCrudRepository;

import com.doj.app.pojo.Order;

/**
 * @author Dinesh.Rajput
 *
 */
public interface SolrOrderRepository extends SolrCrudRepository<Order, Long> {
    
   @Query(name = "Product.findByNamedQuery")
   Page<Product> findByNamedQuery(String searchTerm, Pageable pageable);
    
}

In the above code, we have used the named queries and we have added a Pageable parameter to the findByNamedQuery() method. In the next section, we will discuss how to call this repository using either controller layer or service layer as the following code:

package com.doj.app.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import com.doj.app.pojo.Order;
import com.doj.app.repository.SolrOrderRepository;

/**
 * @author Dinesh.Rajput
 *
 */
@RestController
public class OrderController {
	
	@Autowired
	SolrOrderRepository solrOrderRepository;
	
	...
	
	@GetMapping("/order/desc/{orderDesc}/{page}")
	public List<Order> findOrder(@PathVariable String orderDesc, @PathVariable int page){
		return solrOrderRepository.findByOrderDescription(orderDesc, PageRequest.of(page, 2)).getContent();
	}
	
	@GetMapping("/order/search/{searchTerm}/{page}")
	public List<Order> findOrderBySearchTerm(@PathVariable String searchTerm, @PathVariable int page){
		return solrOrderRepository.findByCustomerQuery(searchTerm, PageRequest.of(page, 2)).getContent();
	}
	
	...
}

As you can see in the above code, how we have used the paginated request from the controller layer by passing the Pageable object to the repository method.

Summary

In this article, we have learned about how to create a paginated query in the Spring Data Solr example by using the PageRequest class and Pageable interface.

Previous
Next