如何使用MongoTemplate获取非嵌套文档分片结果及分页结果
Hey there! Let's tackle your two questions about pagination with MongoTemplate clearly and practically.
To implement proper pagination, you need two key pieces: the data for the current page, and the total number of matching records (to calculate total pages, next/previous page status, etc.). Here's a step-by-step breakdown with code:
- Define pagination parameters: Use
PageRequest(implementsPageable) to set the 0-indexed page number and page size. - Build query criteria: For non-nested documents, reference fields directly in your
Criteria. - Fetch current page data: Use
mongoTemplate.find()with your paginatedQuery. - Count total matching records: Create a copy of your query without pagination (skip/limit) to get the full count of documents that match your criteria.
- Wrap into a
Pageobject: UsePageImpl(Spring Data's defaultPageimplementation) to combine the data, pagination info, and total count.
Example code:
// 1. Set up pagination int pageNumber = 0; // First page (0-indexed) int pageSize = 15; Pageable pageable = PageRequest.of(pageNumber, pageSize); // 2. Build criteria for non-nested document Criteria criteria = Criteria.where("status").is("PAID"); Query paginatedQuery = new Query(criteria).with(pageable); // 3. Get current page content List<Invoice> currentPageContent = mongoTemplate.find(paginatedQuery, Invoice.class); // 4. Get total number of matching records (remove pagination from query) Query countQuery = new Query(criteria); long totalRecords = mongoTemplate.count(countQuery, Invoice.class); // 5. Create the Page object Page<Invoice> paginatedResult = new PageImpl<>(currentPageContent, pageable, totalRecords);
This gives you a fully functional Page object with all pagination metadata (total pages, current page number, hasNext/hasPrevious, etc.).
Looking at your code, the main issue is that mongoTemplate.find() returns a List<Invoice>, not a Page<Invoice>—so your assignment will throw a compilation error. Additionally, you're not calculating the total number of matching records, which is essential for proper pagination.
Here's the corrected version of your code:
final Pageable pageableRequest = PageRequest.of(offset, limit); // Initialize Criteria properly (avoid where("") which can cause unexpected behavior) Criteria criteria = new Criteria(); if (null != type) { criteria = criteria.and("type").is(type); } if (null != revision) { criteria = criteria.and("current_revision_data.data.revision_start").is(revision); } // 1. Create paginated query Query paginatedQuery = new Query(criteria).with(pageableRequest); // 2. Fetch current page data List<Invoice> invoiceList = mongoTemplate.find(paginatedQuery, Invoice.class); // 3. Count total matching records (no pagination parameters) Query countQuery = new Query(criteria); long totalCount = mongoTemplate.count(countQuery, Invoice.class); // 4. Wrap into a Page object Page<Invoice> invoices = new PageImpl<>(invoiceList, pageableRequest, totalCount);
Bonus: Simplify with Spring Data MongoDB's fluent API (2.x+)
If you're using a recent version of Spring Data MongoDB, you can use the fluent query API to avoid manual count calls—it handles the total count automatically:
Page<Invoice> invoices = mongoTemplate.query(Invoice.class) .matching(new Query(criteria).with(pageableRequest)) .page(pageableRequest);
This is cleaner and reduces boilerplate code.
内容的提问来源于stack exchange,提问作者Kency Kurian

