如何使用Mongoose实现分页并返回数据总数?
解决Mongoose分页查询同时返回总数据数的问题
嘿,这个问题我之前也碰到过!你现在的代码里doc.total肯定拿不到值,因为find()配合skip和limit之后返回的只是当前页的文档数组,根本没有total这个属性。想要同时拿到总数据量,有两种常用的方法,我给你详细说下:
方法一:并行执行countDocuments和分页查询(推荐)
这种方法用Promise.all同时发起两个查询——一个统计总数据条数,一个获取当前页的分页数据,效率更高(两个请求并行处理),代码也更清晰。
修改后的代码如下:
router.get('/booksquery', async (req, res) => { try { // 解析分页参数,默认page=1,pageSize=3 const page = parseInt(req.query.page) || 1; const limit = parseInt(req.query.limit) || 3; // 并行执行两个查询:统计总条数 + 获取分页数据 const [total, books] = await Promise.all([ // 这里的空对象是查询条件,要和find里的条件保持一致! Book.countDocuments({}), Book.find({}) .sort({ update_at: -1 }) .skip((page - 1) * limit) .limit(limit) ]); // 返回符合你要求的JSON结构 res.json({ total: total, page: page, pageSize: limit, books: books }); } catch (err) { // 捕获错误并返回500状态码 res.status(500).json(err); } });
关键说明:
- 用
async/await替代回调函数,代码可读性更强,错误处理更方便。 countDocuments({})会统计集合中所有符合条件的文档数(这里空对象表示统计全部),如果后续需要加筛选条件,比如按作者查询,只需要把空对象换成对应的查询条件即可,要和find()里的条件保持一致,否则总条数会不准确。- Mongoose 5.x及以上版本推荐用
countDocuments(),旧版本的count()已经被废弃,尽量避免使用。
方法二:使用聚合管道的$facet阶段
如果你需要处理更复杂的查询(比如多条件筛选、分组后分页),可以用Mongoose的聚合管道,通过$facet在一个请求中同时获取总条数和分页数据:
router.get('/booksquery', async (req, res) => { try { const page = parseInt(req.query.page) || 1; const limit = parseInt(req.query.limit) || 3; const aggregateResult = await Book.aggregate([ // 先排序,和你原来的逻辑一致 { $sort: { update_at: -1 } }, // 使用$facet同时生成两个结果集:total和books { $facet: { total: [{ $count: 'value' }], // 统计总条数 books: [{ $skip: (page - 1) * limit }, { $limit: limit }] // 获取分页数据 } } ]); // 处理总条数的返回结果(如果集合为空,total会是数组空,所以用?.value || 0兜底) const total = aggregateResult[0].total[0]?.value || 0; res.json({ total: total, page: page, pageSize: limit, books: aggregateResult[0].books }); } catch (err) { res.status(500).json(err); } });
关键说明:
$facet可以让我们在一个聚合管道中定义多个子管道,分别返回不同的结果,非常适合复杂场景下的分页查询。- 如果需要添加筛选条件,只需要在
$sort阶段之前加上$match阶段即可,比如{ $match: { author: "郭敬明" } },这样统计的总条数和分页数据都会是符合筛选条件的结果。
注意事项
- 无论用哪种方法,分页参数要做合法性校验,比如page不能小于1,limit不能过大(避免一次性返回过多数据导致性能问题)。
- 如果你的查询有筛选条件,一定要保证统计总条数和分页查询的条件完全一致,否则会出现总条数和实际分页数据不匹配的问题。
内容的提问来源于stack exchange,提问作者wen tian
相关产品推荐
相关产品推荐

