MongoDB分页:使用Limit和Skip时如何获取结果总条数?
获取MongoDB查询总文档数实现分页的方案
针对你用MongoDB\Driver\Query做分页的场景,没法直接通过参数拿到总结果数,以下是两种适配数组传参的实现方式:
方式一:单独执行计数查询
把原查询的过滤条件(文本搜索+国家标签)单独提取出来,用MongoDB\Driver\Command执行计数命令,拿到符合条件的总条数后,再配合原有分页查询返回当前页数据。
示例代码(适配数组传参):
// 原查询的过滤条件数组(文本搜索+国家标签) $filter = [ '$text' => ['$search' => '你的搜索关键词'], 'country' => 'CN' ]; // 构造计数命令的数组参数 $countCmd = [ 'count' => '你的集合名', 'query' => $filter ]; // 执行计数命令 $command = new MongoDB\Driver\Command($countCmd); $countResult = $manager->executeCommand('你的数据库名', $command); $total = current($countResult->toArray())->n; // 原有的分页查询代码(保持不变) $query = new MongoDB\Driver\Query( $filter, [ 'limit' => 10, 'skip' => 20, 'sort' => ['score' => ['$meta' => 'textScore']] ] ); $cursor = $manager->executeQuery('你的数据库名.你的集合名', $query); $currentPageData = $cursor->toArray();
方式二:用聚合查询一次性获取数据和总数
通过$facet聚合阶段,一次查询同时返回当前页数据和总条数,避免两次查询的开销,同样适配数组传参:
示例代码:
$filter = [ '$text' => ['$search' => '你的搜索关键词'], 'country' => 'CN' ]; // 构造聚合管道数组 $pipeline = [ // 应用过滤条件 ['$match' => $filter], // 用facet分两个分支处理 ['$facet' => [ // 获取当前页数据(对应原分页逻辑) 'data' => [ ['$sort' => ['score' => ['$meta' => 'textScore']]], ['$skip' => 20], ['$limit' => 10] ], // 获取总条数 'total' => [ ['$count' => 'total'] ] ]] ]; // 执行聚合命令 $aggregateCmd = [ 'aggregate' => '你的集合名', 'pipeline' => $pipeline, 'cursor' => new stdClass() ]; $command = new MongoDB\Driver\Command($aggregateCmd); $result = $manager->executeCommand('你的数据库名', $command); $aggregateResult = current($result->toArray()); // 提取数据和总数 $currentPageData = $aggregateResult->data; $total = !empty($aggregateResult->total) ? $aggregateResult->total[0]->total : 0;
注意事项
- 两种方式都要保证过滤条件和原查询完全一致,包括文本搜索的关键词、权重(如果有)、国家标签等,否则总数会不准确
- 如果是分片集群,
count命令可能存在精度问题,优先用聚合的方式更可靠 - 数组传参时,要严格对应MongoDB的命令结构,避免语法错误
内容的提问来源于stack exchange,提问作者Richard Andersson
相关产品推荐
相关产品推荐

