MongoDB聚合分页查询如何同时返回匹配文档总条数
MongoDB聚合分页同时返回匹配总数实现方案
要在单次聚合查询中同时拿到$match阶段匹配的全量文档总数、以及分页后的当前页数据,使用$facet阶段即可实现,该阶段支持在同一份输入文档上并行运行多个独立子聚合管道,子管道之间的分页、排序等操作互不干扰。
正确实现代码
return Instances.aggregate([ // 前置条件匹配,所有后续子管道共用该过滤结果 { $match: { /* 填入你的查询条件 */ } }, // 如需排序,把$sort阶段写在这里,两个子管道会共用排序规则,无需重复编写 // { $sort: { age: -1 } }, { $facet: { // 子管道1:统计匹配到的总文档数,不做分页 totalCount: [ { $count: "value" } ], // 子管道2:执行分页,返回当前页数据 data: [ { $skip: skipValue }, { $limit: pageSize } ] } }, // 调整返回结构,把totalCount从数组格式转为数字字段 { $project: { data: 1, totalCount: { $ifNull: [ { $arrayElemAt: ["$totalCount.value", 0] }, 0 ] } } } ])
返回结果格式完全匹配预期:
{ data: [/* 当前页的文档数组 */], totalCount: 54 // 匹配阶段命中的全量文档数,不受分页影响 }
之前方案无效的原因
你之前使用$addFields+$size的方案逻辑不成立:
$addFields是逐文档执行的操作,只会给每一条单独的文档追加字段,无法跨文档统计全量数据$size的作用是计算数组长度,直接传入_id字段本身就不符合运算符的参数要求,自然拿不到正确的总计数。
注意事项
$facet的多个子管道完全独立,data子管道里的$skip、$limit不会影响totalCount的统计结果- 代码中增加了
$ifNull逻辑兜底,当$match阶段没有匹配到任何文档时,totalCount会默认返回0,不会出现字段值为null的异常 - 不要把
$match、$sort这类通用前置阶段写到$facet的子管道里,否则会重复执行计算,浪费查询性能。
内容的提问来源于stack exchange,提问作者juztcode
相关产品推荐
相关产品推荐

