文档菜单
文档首页
/
MongoDB 手册
/ / /

aggregate

本页

  • 定义
  • 兼容性
  • 语法
  • 会话
  • 事务
  • 查询设置
  • 稳定 API
  • 示例
aggregate

使用聚合管道执行聚合操作聚合管道。管道允许用户通过一系列基于阶段的操作处理集合或其他来源的数据。

提示

mongosh中,此命令还可以通过db.aggregate()db.collection.aggregate()辅助方法或使用watch()辅助方法运行.

辅助方法对 mongosh 用户来说很方便,但它们可能不会返回与数据库命令相同水平的信息。在不需要便利性或需要额外的返回字段的情况下,请使用数据库命令。

此命令在以下环境中部署的部署中可用

  • MongoDB Atlas:云中MongoDB部署的完全托管服务

重要

此命令在M0、M2和M5集群中支持有限。有关更多信息,请参阅不受支持的命令。

已更改在版本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
布尔值

可选。指定返回有关管道处理的信息。

多文档事务中不可用。

allowDiskUse

布尔值

可选。

使用此选项可覆盖特定查询的 allowDiskUseByDefault。您可以使用此选项来:

  • 在默认允许磁盘使用的情况下禁止磁盘使用。

  • 在默认禁止磁盘使用的情况下允许磁盘使用。

从 MongoDB 6.0 开始,如果 allowDiskUseByDefault 设置为 true 并且服务器需要一个超过 100 兆字节的内存来执行管道执行阶段,MongoDB 会自动将临时文件写入磁盘,除非查询指定了 { allowDiskUse: false }

有关详细信息,请参阅 allowDiskUseByDefault

数据库分析器日志消息和诊断日志消息包括一个 usedDisk 指示器,如果任何聚合阶段因为 内存限制 而将数据写入临时文件。

cursor
文档

指定一个包含控制游标对象创建的选项的文档。

MongoDB 移除了不带有 cursor 选项的 aggregate 命令的用法,除非命令包含 explain 选项。除非您包含 explain 选项,否则您必须指定游标选项。

  • 要指定具有默认批量大小的游标,请指定 cursor: {}

  • 要指定具有非默认批量大小的游标,请使用 cursor: { batchSize: <num> }

maxTimeMS
非负整数

可选。

指定一个以毫秒为单位的时间限制。如果您没有指定 maxTimeMS 的值,操作将不会超时。值 0 明确指定了默认的无限制行为。

MongoDB 使用与 db.killOp() 相同的机制终止超过其分配时间限制的操作。MongoDB 仅在操作的一个指定的 中断点 处终止操作。

bypassDocumentValidation
布尔值

可选。仅当您指定了 $out$merge 聚合阶段时适用。

允许 aggregate 在操作期间绕过文档验证。这使您能够插入不满足验证要求的文档。

readConcern
文档

可选。指定 读取关注点。

readConcern 选项的语法如下: readConcern: { level: <value> }

可能的读取关注点级别有

有关读取关注点级别的更多信息,请参阅 读取关注点级别。

无法在 $out 阶段与读取关注点 "linearizable" 一起使用。换句话说,如果您为 db.collection.aggregate() 指定了 "linearizable" 读取关注点,则无法在管道中包含 $out 阶段。

无法在 $merge 阶段与读取关注点 "linearizable" 一起使用。也就是说,如果您为 db.collection.aggregate() 指定了 "linearizable" 读取关注点,则无法在管道中包含 $merge 阶段。

collation
文档

可选。

指定操作中使用的 排序规则。

排序规则 允许用户指定字符串比较的语言特定规则,例如字母大小写和重音符号的规则。

排序规则选项的语法

collation: {
locale: <string>,
caseLevel: <boolean>,
caseFirst: <string>,
strength: <int>,
numericOrdering: <boolean>,
alternate: <string>,
maxVariable: <string>,
backwards: <boolean>
}

指定排序规则时,locale 字段是必需的;所有其他排序规则字段都是可选的。有关字段的说明,请参阅 排序规则文档。

如果未指定排序,但集合有默认排序规则(请参阅 db.createCollection()),操作将使用集合指定的排序规则。

如果没有为集合或操作指定排序规则,MongoDB 将使用之前版本中用于字符串比较的简单二进制比较。

您不能为操作指定多个排序规则。例如,您不能按字段指定不同的排序规则,或者在执行带有排序的查找时,不能为查找和排序使用不同的排序规则。

提示
字符串或文档

可选。指定用于聚合的索引。该索引是在运行聚合操作的基础集合/视图上的索引。

可以通过索引名称或索引规范文档指定索引。

hint$lookup$graphLookup 阶段不适用。

注释
任何

可选。为该命令附加的用户提供的注释。一旦设置,此注释将出现在以下位置的该命令记录旁边

注释可以是任何有效的 BSON 类型(字符串、整数、对象、数组等)。

任何在 aggregate 命令上设置的注释都将由在 aggregate 游标上运行的任何后续 getMore 命令继承。

写入关注点
文档

可选。一个文档,它表达了与 写入关注点 一起使用的 $out$merge 阶段一起使用的写入关注点。

省略以使用 $out$merge 阶段的默认写入关注点。

let
文档

可选。

指定一个包含变量列表的文档。这允许您通过将变量与查询文本分开来提高命令的可读性。

文档语法是

{
<variable_name_1>: <expression_1>,
...,
<variable_name_n>: <expression_n>
}

变量设置为表达式返回的值,并且之后不能更改。

要访问命令中的变量值,请使用双美元符号前缀($$)以及变量名,形式为 $$<变量名>。例如:$$targetTotal

要在管道中的 $match 阶段使用变量来过滤结果,必须在使用 $expr 操作符时访问该变量。

有关使用 let 和变量的完整示例,请参阅 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 命令刷新会话。有关更多信息,请参阅会话空闲超时

aggregate 可以在 分布式事务 中使用。

但是,以下阶段不允许在事务中使用

您也不能指定 explain 选项。

  • 对于在事务外创建的光标,您不能在事务内调用 getMore

  • 对于在事务中创建的光标,您不能在事务外调用 getMore

重要

在大多数情况下,分布式事务相对于单文档写入会带来更高的性能成本,分布式事务的可用性不应取代有效的架构设计。对于许多场景,非规范化数据模型(嵌入文档和数组) 将继续是您数据和用例的最佳选择。也就是说,在许多场景中,适当地对数据进行建模将最大限度地减少分布式事务的需求。

有关事务的附加使用注意事项(例如运行时限制和oplog大小限制),请参阅生产注意事项

对于不包含 aggregate$out$merge 阶段的操作

从 MongoDB 4.2 版本开始,如果发出 aggregate 的客户端在操作完成之前断开连接,MongoDB 将使用 killOp 命令将 aggregate 标记为终止。

在版本8.0.

您可以使用查询设置来设置索引提示、设置 操作拒绝过滤器 以及其他字段。这些设置应用于整个集群上的 查询形状。集群在关闭后仍保留这些设置。

查询优化器在查询计划阶段将查询设置作为附加输入使用,这会影响选择的查询计划。您还可以使用查询设置来阻止查询形状。

有关添加查询设置和示例,请参阅 setQuerySettings

您可以添加针对 finddistinctaggregate 命令的查询设置。

查询设置具有更多功能,并且比已弃用的 索引过滤器 更受欢迎。

要删除查询设置,请使用 removeQuerySettings。要获取查询设置,请在聚合管道中使用 $querySettings 阶段。

当使用 稳定API V1

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 操作,第二阶段过滤该操作的结果。

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 }
)

注意

解释输出可能在不同的版本之间发生变化。

从 MongoDB 6.0 版本开始,需要超过 100 兆内存才能执行的管道阶段默认将临时文件写入磁盘。这些临时文件将在管道执行期间持续存在,可能会影响实例的存储空间。在 MongoDB 的早期版本中,您必须传递 { allowDiskUse: true } 到单个 findaggregate 命令以启用此行为。

单个 findaggregate 命令可以通过以下方式覆盖 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 } },表示第一个批次为空。此批量大小对于快速返回光标或错误消息而不进行大量服务器端工作非常有用。

要指定后续getMore操作(初始批次之后)的批量大小,请在运行getMore命令时使用batchSize字段。

排序规则 允许用户指定字符串比较的语言特定规则,例如字母大小写和重音符号的规则。

集合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",以读取已确认为写入到多数节点的最新数据副本。

重要

  • 您可以为包含读取关注级别的聚合操作指定"majority"(多数)级别,其中包含一个$out阶段。

  • 无论读取关注级别如何,节点上最新的数据可能并不反映系统数据的最新版本。

db.restaurants.aggregate(
[ { $match: { rating: { $lt: 5 } } } ],
{ readConcern: { level: "majority" } }
)

为确保单个线程可以读取自己的写入操作,请对副本集的主节点使用"majority"读取关注级别和"majority"写入关注级别。

在版本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 }
} )

提示

另请参阅

返回

聚合