使用MongoDB聚合查询且带Limit时,如何获取匹配文档总数?
解决MongoDB分页查询时获取总匹配数的方案
方法一:使用$facet阶段一次聚合获取数据与总数
通过$facet可以在单次聚合中并行执行多个管道,一个处理分页数据,另一个统计总匹配数,避免重复执行匹配逻辑,效率更高。
修改后的代码示例:
const result = await searchAgent.aggregate([ // 共享的匹配条件,和原查询一致 {$match: {id: Number(fid), status: {$regex: status, $options: 'i'}}}, // 拆分两个并行处理管道 {$facet: { // 分页数据管道:保留原有的排序、跳过、限制逻辑 paginatedData: [ {$sort: {[order_by]: order === 'desc' ? -1 : 1}}, {$skip: skip}, {$limit: pagelimit} ], // 总数统计管道:直接统计匹配后的文档数量 totalCount: [ {$count: 'count'} ] }} ]); // 提取最终结果 const search = result[0].paginatedData; // 处理无匹配文档的情况,默认总数为0 const total = result[0].totalCount[0]?.count || 0;
方法二:拆分两次查询(简单直接)
先单独执行匹配+统计总数的查询,再执行原分页查询。为避免重复编写匹配条件,建议将匹配逻辑抽离为变量复用。
代码示例:
// 抽离匹配条件,复用两次查询 const matchCondition = {id: Number(fid), status: {$regex: status, $options: 'i'}}; // 第一步:查询总匹配数 const totalResult = await searchAgent.aggregate([ {$match: matchCondition}, {$count: 'count'} ]); const total = totalResult[0]?.count || 0; // 第二步:执行原分页查询 const search = await searchAgent.aggregate([ {$match: matchCondition}, {$sort: {[order_by]: order === 'desc' ? -1 : 1}}, {$skip: skip}, {$limit: pagelimit}, ]);
注意事项
- 如果
status字段有索引,使用$regex加$options: 'i'会导致索引失效,数据量大时可能影响性能,可考虑提前将status存储为小写形式,查询时直接匹配小写值。 - 两种方法中,
$facet更适合复杂匹配场景,能减少一次数据库请求;拆分查询则逻辑更直观,适合简单场景。
内容的提问来源于stack exchange,提问作者Akshay A
相关产品推荐
相关产品推荐

