首页 > 解决方案 > 如何在聚合管道中执行 $match 阶段时添加限制

问题描述

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

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

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

标签: mongodbaggregation-framework

解决方案


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

例如:

> db.test.find()
{ "_id": 0 }
{ "_id": 1 }
{ "_id": 2 }
{ "_id": 3 }
{ "_id": 4 }

假设我想使用一个$match舞台,然后是$limit舞台。explain()在聚合上使用:

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

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

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

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


推荐阅读