如何在聚合管道中执行 $match 阶段时添加限制

Mem*_*eam 3 mongodb aggregation-framework

在执行 find() 查询时,我可以传递限制和排序等选项。我认为,这意味着数据库将在找到有限数量的文档后停止尝试过滤匹配文档。

当尝试使用聚合管道完成相同的事情时,我将 find() 中的相同查询作为 $match 阶段,但我无法指定限制。

$limit 的问题在于它只发生在下一阶段,因此 mongo 将在将集合中的每个文档传递到下一阶段之前处理它,随着集合大小的增加,这可能会变得非常慢。

kev*_*adi 7

聚合框架就像一个流,因此如果$limit管道中有一个阶段,一旦达到限制,它将停止处理。

例如:

> db.test.find()
{ "_id": 0 }
{ "_id": 1 }
{ "_id": 2 }
{ "_id": 3 }
{ "_id": 4 }
Run Code Online (Sandbox Code Playgroud)

假设我想$match依次使用一个阶段$limitexplain()在聚合上使用:

> db.test.explain('executionStats').aggregate([
      {$match: {_id: {$lte: 3}}},
      {$limit: 1}
  ])
...
        "executionStats": {
          "executionSuccess": true,
          "nReturned": 1,
          "executionTimeMillis": 0,
          "totalKeysExamined": 1,
          "totalDocsExamined": 1,
...
Run Code Online (Sandbox Code Playgroud)

解释输出显示,由于阶段, MongoDB 仅检查了 1 个键 ( totalKeysExamined: 1) 和 1 个文档 ( totalDocsExamined: 1),以返回 1 个文档 ( ) 。尽管我将其指定为 match ,它应该选择 4 个文档。nReturned: 1$limit_id <= 3

请注意,大多数阶段都是这样工作的,但某些阶段除外,例如$group需要收集所有必需的文档才能对它们进行分组。放在$limit后面$group不会使$limit阶段充当流,因为它必须等待阶段$group完成其进程才能限制输出。

查看解释结果聚合管道优化以获取更多信息。