Spring Custom Query with pageable

27,639

Solution 1

As you figured out, MongoTemplate doesn't support the complete page abstraction. Like KneeLess said you can use the @Query-Annotation to do some custom queries.

In case this isn't enough for you, can use utilize the Spring Repository PageableExecutionUtils in combination with your MongoTemplate.

For example like this:

@Override
public Page<XXX> findSophisticatedXXX(/* params, ... */ @NotNull Pageable pageable) {

    Query query = query(
            where("...")
            // ... sophisticated query ...
    ).with(pageable);

    List<XXX> list = mongoOperations.find(query, XXX.class);
    return PageableExecutionUtils.getPage(list, pageable,
              () -> mongoOperations.count((Query.of(query).limit(-1).skip(-1), XXX.class));
}

Spring Repositories are doing the same. As you can see here, they fire two queries as well.

Solution 2

You can define your query using Spring's @Query annotation and then define a Pageable as the last parameter:

public interface FooRepository extends MongoRepository<Foo,String> {    
    @Query(value="{'name': ?0}")
    Page<Foo> findByMethod(String name, Pageable pageable);
}

Then, use it like so:

Page<Foo> fooPage = fooRepository.findByMethod("John", new PageRequest(0,20));

Solution 3

Just putting it out in case someone needs it.

SpringData has a method for custom query:

final Pageable pageableRequest = new PageRequest(0, 2);
Query query = new Query();
query.with(pageableRequest);

Solution 4

By extending Spring Data PagingAndSortingRepository interface you can get some common methods such as save, find, findAll and delete and also you can add your own custom queries:

public interface Repository extends PagingAndSortingRepository<Book, ID extends Serializable> {

    // Common method
    Page<Book> findAll(Pageable pageable);

    // Custom query based on Spring Data naming convention
    Page<Book> findByNameOrDescription(String name, String description, Pageable pageable);

}

Solution 5

Here is the example without loading all the data in memory.

@Autowired
private MongoTemplate mongoTemplate; 

    @Override
public Page<YourClass> findAll(/* params, ... */ @NotNull Pageable pageable) {
    Query query = query(
            where("...")
            // ... your query ...
    ).with(pageable);
    Long totalCount = mongoTemplate.count(query, YourClass.class);
    List<YourClass> results = mongoTemplate.find(query.with(pageable), YourClass.class);
    Page<YourClass> resultsWithPage = PageableExecutionUtils.getPage(results, pageable, () -> totalCount);
    return resultsWithPage;
}
Share:
27,639
Trivikrama
Author by

Trivikrama

Updated on October 06, 2021

Comments

  • Trivikrama
    Trivikrama over 2 years

    I want to to implement pagination in spring application.I know using repository we can implement pagination but we can not write our own query for data retrieve there are limited methods in repository that too there is no method accepting query class.

    If we want to write our custom query to retrieve data from mongodb we have to use mongotemaplete, as i know with mongotemplate we can not implement pagination.

    Is there any another way to implement pagination along with db queries. any one can help me.

  • conan_z
    conan_z over 6 years
    That killer reference! I have being searching for hours! xD
  • Henrique Rocha
    Henrique Rocha about 5 years
    You have an extra semi-colon at the end of the Query annotation, can you remove it? Thanks ;-)
  • Cotta
    Cotta about 4 years
    Fantastic! I spent hours because I didn't have the Query.of(query).limit(-1).skip(-1), but just a straight query.
  • vinicius gati
    vinicius gati over 3 years
    cant use it from repository, it says its protected access
  • arxakoulini
    arxakoulini about 3 years
    will this load all the records in memory and then paginate them afterwards?
  • randomsimon
    randomsimon almost 3 years
    @viniciusgati, I think that's because the API has changed in later versions. The new equivalent is PageRequest.of(0, 2)
  • teuber789
    teuber789 over 2 years
    Extra semi-colon removed.
  • Ferdynand Kiepski
    Ferdynand Kiepski over 2 years
    You can also have Pageable parameters as first parameter. You won't need to change ?0 to ?1, because Pageable is not considered as real parameter to @Query.