mongodb - 如何在聚合管道中执行 $match 阶段时添加限制
问题描述
在进行 find() 查询时,我可以传递限制和排序等选项。我认为,这意味着数据库将在找到限制数量的文档后停止尝试过滤匹配的文档。
当尝试使用聚合管道完成相同的事情时,我将 find() 中的查询与 $match 阶段相同,但我无法指定限制。
$limit 的问题在于它只发生在下一阶段,因此 mongo 将在将集合中的每个文档传递到下一阶段之前处理它,随着集合大小的增加,这可能会变得非常慢。
解决方案
聚合框架就像一个流,所以如果你$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
需要收集所有必需文档才能对它们进行分组的阶段。放置$limit
after$group
不会使$limit
阶段充当流,因为它必须等待$group
阶段完成其过程才能限制输出。
推荐阅读
- javascript - puppeteer 的 document.styleSheets
- java - Java DateTimeFormatter 未按预期解析
- artifactory - 如何在下载工件之前检查来自用户插件的构建信息?
- mysql - 更新主键索引行的时间很慢
- save - 为什么我的 Discord 资产在上传后没有保存?
- javascript - 失去焦点/ onBlur时反应textarea回调
- android - 如何将所有 Retrofit 网络代码分组到一个单独的类中并在没有紧密耦合或内存泄漏的情况下传达响应?MVVM
- android - 如何将工件转换 api 任务结果连接到 Android Studio
- javascript - 如何将 useRef 与 Typescript/Formik 一起使用?
- java - Eclipse 更新 Maven 项目 > 错误 SAXParserFactory