如何获取MongoDB分页总页数?附现有实现代码与数据
Hey there! The issue you're facing with incorrect totalPages is because right now you're passing filter.size() (the number of elements in the current page) as the total element count to PageImpl. To get the correct total pages, you need to first calculate the total number of documents that match your query criteria, not just the ones loaded for the current page.
Let's fix this step by step:
1. Extract Shared Query Criteria
First, pull out your search criteria into a reusable variable to avoid duplicating code across count and pagination queries:
Criteria criteria = new Criteria().orOperator( Criteria.where("name").regex(query, "i"), Criteria.where("details.brand").regex(query, "i"), Criteria.where("details.tags.tags1").regex(query, "i"), Criteria.where("details.tags.tags2").regex(query, "i"), Criteria.where("details.tags.tags3").regex(query, "i") );
2. Calculate Total Matching Documents
You need to get the total number of documents that fit your search terms. There are two straightforward ways to do this:
Option 1: Use mongoTemplate.count() (Simplest for Basic Counts)
This is the cleanest approach if you don't need complex aggregation logic for counting:
Long totalElements = mongoTemplate.count(Query.query(criteria), "Product");
Option 2: Use Aggregation Count (For Complex Scenarios)
If you ever need to add grouping or other logic to your count, use an aggregation pipeline:
Aggregation countAggregation = Aggregation.newAggregation( Aggregation.match(criteria), Aggregation.count().as("total") ); Long totalElements = mongoTemplate.aggregate(countAggregation, "Product", Document.class) .getMappedResults() .stream() .findFirst() .map(doc -> doc.getLong("total")) .orElse(0L);
3. Update Pagination Aggregation to Use Pageable
Instead of hardcoding skip(page *4) and limit(4), leverage the pageable parameter you're already receiving. This makes your code flexible to different page sizes configured by the caller:
Aggregation paginationAggregation = Aggregation.newAggregation( Aggregation.match(criteria), Aggregation.skip(pageable.getOffset()), // Automatically computes pageNumber * pageSize Aggregation.limit(pageable.getPageSize()) ); List<Products> filter = mongoTemplate.aggregate(paginationAggregation, "Product", Products.class).getMappedResults();
4. Return PageImpl with Correct Total Elements
Finally, pass the real totalElements (not the current page's size) to the PageImpl constructor. This lets Spring's PageImpl calculate the correct totalPages automatically:
return new PageImpl<>(filter, pageable, totalElements);
Full Updated Method
@GetMapping("/engine/search") public PageImpl<Products> engineSearch(@RequestParam("p") String query, @RequestParam(value = "page", defaultValue = "0") int page, Pageable pageable) { // Define shared search criteria Criteria criteria = new Criteria().orOperator( Criteria.where("name").regex(query, "i"), Criteria.where("details.brand").regex(query, "i"), Criteria.where("details.tags.tags1").regex(query, "i"), Criteria.where("details.tags.tags2").regex(query, "i"), Criteria.where("details.tags.tags3").regex(query, "i") ); // Get total number of matching documents Long totalElements = mongoTemplate.count(Query.query(criteria), "Product"); // Build pagination aggregation Aggregation paginationAggregation = Aggregation.newAggregation( Aggregation.match(criteria), Aggregation.skip(pageable.getOffset()), Aggregation.limit(pageable.getPageSize()) ); List<Products> filter = mongoTemplate.aggregate(paginationAggregation, "Product", Products.class).getMappedResults(); // Return properly populated PageImpl return new PageImpl<>(filter, pageable, totalElements); }
Why This Fixes the Total Pages Issue
- The
totalElementsvariable now holds the full count of documents matching your search, not just the subset in the current page. PageImpluses this total count and thepageable'spageSizeto computetotalPagesusing the formula:ceil(totalElements / pageSize)(exactly what you need for accurate pagination metadata).- Using
pageable.getOffset()andpageable.getPageSize()aligns your code with Spring Data's standard pagination patterns, making it more maintainable and flexible.
内容的提问来源于stack exchange,提问作者Taylor Marshall

