aggregate
定义
aggregate
使用聚合管道执行聚合操作聚合管道。管道允许用户通过一系列基于阶段的操作处理集合或其他来源的数据。
提示
在
mongosh
中,此命令还可以通过db.aggregate()
和db.collection.aggregate()
辅助方法或使用watch()
辅助方法运行.辅助方法对
mongosh
用户来说很方便,但它们可能不会返回与数据库命令相同水平的信息。在不需要便利性或需要额外的返回字段的情况下,请使用数据库命令。
兼容性
此命令在以下环境中部署的部署中可用
MongoDB Atlas:云中MongoDB部署的完全托管服务
重要
此命令在M0、M2和M5集群中支持有限。有关更多信息,请参阅不受支持的命令。
MongoDB Enterprise:基于订阅的、自行管理的MongoDB版本
MongoDB Community:源代码可用、免费使用和自行管理的MongoDB版本
语法
已更改在版本5.0.
命令有以下语法
db.runCommand( { aggregate: "<collection>" || 1, pipeline: [ <stage>, <...> ], explain: <boolean>, allowDiskUse: <boolean>, cursor: <document>, maxTimeMS: <int>, bypassDocumentValidation: <boolean>, readConcern: <document>, collation: <document>, hint: <string or document>, comment: <any>, writeConcern: <document>, let: <document> // Added in MongoDB 5.0 } )
命令字段
aggregate
命令接受以下字段作为参数
字段 | 类型 | 描述 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
aggregate | 字符串 | 作为聚合管道输入的集合或视图名称。使用 1 用于与集合无关的命令。 | ||||||||||
管道 | 数组 | 一个包含聚合管道阶段的数组,这些阶段作为聚合管道的一部分处理和转换文档流。 | ||||||||||
explain | 布尔值 | 可选。指定返回有关管道处理的信息。 在多文档事务中不可用。 | ||||||||||
| 布尔值 | 可选。 使用此选项可覆盖特定查询的
从 MongoDB 6.0 开始,如果 有关详细信息,请参阅 数据库分析器日志消息和诊断日志消息包括一个 | ||||||||||
cursor | 文档 | 指定一个包含控制游标对象创建的选项的文档。 MongoDB 移除了不带有
| ||||||||||
maxTimeMS | 非负整数 | 可选。 指定一个以毫秒为单位的时间限制。如果您没有指定 MongoDB 使用与 | ||||||||||
bypassDocumentValidation | 布尔值 | |||||||||||
readConcern | 文档 | 可选。指定 读取关注点。
可能的读取关注点级别有
有关读取关注点级别的更多信息,请参阅 读取关注点级别。 无法在 无法在 | ||||||||||
collation | 文档 | 可选。 指定操作中使用的 排序规则。 排序规则 允许用户指定字符串比较的语言特定规则,例如字母大小写和重音符号的规则。 排序规则选项的语法
指定排序规则时, 如果未指定排序,但集合有默认排序规则(请参阅 如果没有为集合或操作指定排序规则,MongoDB 将使用之前版本中用于字符串比较的简单二进制比较。 您不能为操作指定多个排序规则。例如,您不能按字段指定不同的排序规则,或者在执行带有排序的查找时,不能为查找和排序使用不同的排序规则。 | ||||||||||
提示 | 字符串或文档 | |||||||||||
注释 | 任何 | 可选。为该命令附加的用户提供的注释。一旦设置,此注释将出现在以下位置的该命令记录旁边
注释可以是任何有效的 BSON 类型(字符串、整数、对象、数组等)。 任何在 | ||||||||||
写入关注点 | 文档 | |||||||||||
let | 文档 | 可选。 指定一个包含变量列表的文档。这允许您通过将变量与查询文本分开来提高命令的可读性。 文档语法是
变量设置为表达式返回的值,并且之后不能更改。 要访问命令中的变量值,请使用双美元符号前缀( 要在管道中的 有关使用 新在版本5.0. |
MongoDB 移除了不带有 cursor
选项的 aggregate
命令的用法,除非命令包含 explain
选项。除非您包含 explain
选项,否则您必须指定游标选项。
要指定具有默认批量大小的游标,请指定
cursor: {}
。要指定具有非默认批量大小的游标,请使用
cursor: { batchSize: <num> }
。
有关聚合管道的更多信息,请参阅
会话
对于在会话内部创建的游标,您不能在会话外部调用 getMore
。
同样,对于在会话外部创建的游标,您不能在会话内部调用 getMore
。
会话空闲超时
MongoDB 驱动程序和 mongosh
将所有操作与服务器会话相关联,除了未确认的写操作。对于没有明确与会话关联的操作(即使用 Mongo.startSession()
),MongoDB 驱动程序和 mongosh
会创建一个隐式会话并将其与操作关联。
如果一个会话空闲时间超过30分钟,MongoDB服务器将标记该会话为过期,并且可能随时关闭它。当MongoDB服务器关闭会话时,它也会终止与该会话关联的任何正在进行的操作和打开的光标。这包括配置了 noCursorTimeout()
或 maxTimeMS()
大于30分钟的光标。
对于返回光标的操作,如果光标可能空闲超过30分钟,请使用 Mongo.startSession()
在显式会话中执行操作,并定期使用 refreshSessions
命令刷新会话。有关更多信息,请参阅会话空闲超时。
事务
但是,以下阶段不允许在事务中使用
您也不能指定 explain
选项。
重要
在大多数情况下,分布式事务相对于单文档写入会带来更高的性能成本,分布式事务的可用性不应取代有效的架构设计。对于许多场景,非规范化数据模型(嵌入文档和数组) 将继续是您数据和用例的最佳选择。也就是说,在许多场景中,适当地对数据进行建模将最大限度地减少分布式事务的需求。
有关事务的附加使用注意事项(例如运行时限制和oplog大小限制),请参阅生产注意事项。
客户端断开
对于不包含 aggregate
或 $out
或 $merge
阶段的操作
从 MongoDB 4.2 版本开始,如果发出 aggregate
的客户端在操作完成之前断开连接,MongoDB 将使用 killOp
命令将 aggregate
标记为终止。
查询设置
新在版本8.0.
您可以使用查询设置来设置索引提示、设置 操作拒绝过滤器 以及其他字段。这些设置应用于整个集群上的 查询形状。集群在关闭后仍保留这些设置。
查询优化器在查询计划阶段将查询设置作为附加输入使用,这会影响选择的查询计划。您还可以使用查询设置来阻止查询形状。
有关添加查询设置和示例,请参阅 setQuerySettings
。
您可以添加针对 find
、distinct
和 aggregate
命令的查询设置。
查询设置具有更多功能,并且比已弃用的 索引过滤器 更受欢迎。
要删除查询设置,请使用 removeQuerySettings
。要获取查询设置,请在聚合管道中使用 $querySettings
阶段。
稳定API
当使用 稳定API V1
您不能在
aggregate
命令中使用以下阶段不要在
aggregate
命令中包含explain
字段。如果包含,服务器将返回 APIStrictError 错误。当使用
$collStats
阶段时,您只能使用count
字段。没有其他$collStats
字段可用。
示例
MongoDB 移除了不带有 cursor
选项的 aggregate
命令的用法,除非命令包含 explain
选项。除非您包含 explain
选项,否则您必须指定游标选项。
要指定具有默认批量大小的游标,请指定
cursor: {}
。要指定具有非默认批量大小的游标,请使用
cursor: { batchSize: <num> }
。
与直接运行 aggregate
命令相比,大多数用户应使用在 mongosh
或其驱动程序中提供的等效辅助函数 db.collection.aggregate()
。在 2.6 及更高版本中,db.collection.aggregate()
辅助函数始终返回一个游标。
除前两个示例演示命令语法外,本页中的其他示例均使用 db.collection.aggregate()
辅助函数。
多阶段管道聚合数据
一个包含以下文档的集合 articles
:
{ _id: ObjectId("52769ea0f3dc6ead47c9a1b2"), author: "abc123", title: "zzz", tags: [ "programming", "database", "mongodb" ] }
以下示例在 articles
集合上执行了一个 aggregate
操作,计算集合中 tags
数组中每个不同元素的出现次数。
db.runCommand( { aggregate: "articles", pipeline: [ { $project: { tags: 1 } }, { $unwind: "$tags" }, { $group: { _id: "$tags", count: { $sum : 1 } } } ], cursor: { } } )
在 mongosh
中,此操作可以使用以下方式使用 db.collection.aggregate()
辅助函数:
db.articles.aggregate( [ { $project: { tags: 1 } }, { $unwind: "$tags" }, { $group: { _id: "$tags", count: { $sum : 1 } } } ] )
在管理数据库上使用 $currentOp
以下示例在管理数据库上运行了两个阶段的管道。第一阶段运行 $currentOp
操作,第二阶段过滤该操作的结果。
db.adminCommand( { aggregate : 1, pipeline : [ { $currentOp : { allUsers : true, idleConnections : true } }, { $match : { shard : "shard01" } } ], cursor : { } } )
注意
聚合命令 aggregate
没有指定集合,而是采用形式 {aggregate: 1}
。这是因为初始的 $currentOp
阶段不从集合中获取输入。它生成自己的数据,该数据由管道的其余部分使用。
已添加新的 db.aggregate()
辅助函数,以帮助运行无集合聚合,例如上述聚合也可以像这样运行:
返回聚合操作的详细信息
以下聚合操作将可选字段 explain
设置为 true
以返回有关聚合操作的信息。
db.orders.aggregate([ { $match: { status: "A" } }, { $group: { _id: "$cust_id", total: { $sum: "$amount" } } }, { $sort: { total: -1 } } ], { explain: true } )
注意
解释输出可能在不同的版本之间发生变化。
与 allowDiskUseByDefault
的交互
从 MongoDB 6.0 版本开始,需要超过 100 兆内存才能执行的管道阶段默认将临时文件写入磁盘。这些临时文件将在管道执行期间持续存在,可能会影响实例的存储空间。在 MongoDB 的早期版本中,您必须传递 { allowDiskUse: true }
到单个 find
和 aggregate
命令以启用此行为。
单个 find
和 aggregate
命令可以通过以下方式覆盖 allowDiskUseByDefault
参数:
当
allowDiskUseByDefault
设置为false
时,使用{ allowDiskUse: true }
允许写入临时文件到磁盘。当
allowDiskUseByDefault
设置为true
时,使用{ allowDiskUse: false }
禁止写入临时文件到磁盘。
数据库分析器日志消息和诊断日志消息包括一个 usedDisk
指示器,如果任何聚合阶段因为 内存限制 而将数据写入临时文件。
指定批量大小数据
要指定一个初始批量大小,请在cursor
字段中指定batchSize
,如下例所示
db.orders.aggregate( [ { $match: { status: "A" } }, { $group: { _id: "$cust_id", total: { $sum: "$amount" } } }, { $sort: { total: -1 } }, { $limit: 2 } ], { cursor: { batchSize: 0 } } )
指定初始批量大小的文档{ cursor: { batchSize: 0 } }
,表示第一个批次为空。此批量大小对于快速返回光标或错误消息而不进行大量服务器端工作非常有用。
指定排序规则
排序规则 允许用户指定字符串比较的语言特定规则,例如字母大小写和重音符号的规则。
集合myColl
具有以下文档
{ _id: 1, category: "café", status: "A" } { _id: 2, category: "cafe", status: "a" } { _id: 3, category: "cafE", status: "a" }
以下聚合操作包含排序规则选项
db.myColl.aggregate( [ { $match: { status: "A" } }, { $group: { _id: "$category", count: { $sum: 1 } } } ], { collation: { locale: "fr", strength: 1 } } );
有关排序规则字段的说明,请参阅排序规则文档。
提示索引
创建一个包含以下文档的集合 foodColl
db.foodColl.insertMany( [ { _id: 1, category: "cake", type: "chocolate", qty: 10 }, { _id: 2, category: "cake", type: "ice cream", qty: 25 }, { _id: 3, category: "pie", type: "boston cream", qty: 20 }, { _id: 4, category: "pie", type: "blueberry", qty: 15 } ] )
创建以下索引
db.foodColl.createIndex( { qty: 1, type: 1 } ); db.foodColl.createIndex( { qty: 1, category: 1 } );
以下聚合操作包含 hint
选项以强制使用指定的索引
db.foodColl.aggregate( [ { $sort: { qty: 1 }}, { $match: { category: "cake", qty: 10 } }, { $sort: { type: -1 } } ], { hint: { qty: 1, category: 1 } } )
覆盖默认读取关注
要覆盖默认的读取关注级别,请使用 readConcern
选项。在原始 aggregate
命令中指定的 readConcern
级别被用于 getMore
命令。
您不能在读取关注 "linearizable"
时使用 $out
或 $merge
阶段。也就是说,如果您为 "linearizable"
读取关注指定 db.collection.aggregate()
,您不能在管道中包含这两个阶段。
以下对副本集的操作指定了 读取关注 为 "majority"
,以读取已确认为写入到多数节点的最新数据副本。
db.restaurants.aggregate( [ { $match: { rating: { $lt: 5 } } } ], { readConcern: { level: "majority" } } )
为确保单个线程可以读取自己的写入操作,请对副本集的主节点使用"majority"
读取关注级别和"majority"
写入关注级别。
在let
中使用变量
新在版本5.0.
要定义可以在命令的其他部分访问的变量,请使用let
选项。
注意
要在管道中的$match
阶段使用变量来过滤结果,必须在$expr
操作符内访问该变量。
创建一个包含蛋糕口味销售的cakeSales
集合
db.cakeSales.insertMany( [ { _id: 1, flavor: "chocolate", salesTotal: 1580 }, { _id: 2, flavor: "strawberry", salesTotal: 4350 }, { _id: 3, flavor: "cherry", salesTotal: 2150 } ] )
以下示例
检索
salesTotal
大于3000的蛋糕,即_id
为2的蛋糕在
let
中定义一个targetTotal
变量,在$gt
中使用它作为$$targetTotal
db.runCommand( { aggregate: db.cakeSales.getName(), pipeline: [ { $match: { $expr: { $gt: [ "$salesTotal", "$$targetTotal" ] } } }, ], cursor: {}, let: { targetTotal: 3000 } } )