You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:31:59