Docs 菜单
Docs 主页
/
MongoDB Manual
/ / /

db.collection.aggregate()

在此页面上

  • 定义
  • 兼容性
  • 语法
  • 行为
  • 示例

带驱动程序的 MongoDB

本页面提供 mongosh 方法的相关信息。要查看 MongoDB 驱动程序中的等效方法,请参阅编程语言的相应页面:

C#Java SyncNode.jsPyMongoCC++GoJava RSKotlin CoroutineKotlin SyncPHPMotorMongoidRustScalaSwift
db.collection.aggregate(pipeline, options)

计算集合或 视图中数据的聚合值。

返回:
  • 在聚合分析管道的最后阶段生成的文档游标
  • 如果管道包含 explain 选项,查询将返回一个详细说明聚合操作处理的文档。
  • 如果管道包含 $out$merge 操作符,查询将返回一个空游标。

可以使用 db.collection.aggregate() 查找托管在以下环境中的部署:

aggregate() 方法采用以下形式:

db.collection.aggregate( <pipeline>, <options> )

aggregate() 方法使用以下参数:

Parameter
类型
说明
pipeline
阵列
一系列数据聚合操作或阶段。请参阅

聚合管道操作符以了解详情。

该方法仍然可以接受管道阶段作为单独的参数,而不是作为数组中的元素;但是,如果您未将 pipeline 指定为数组,则无法指定 options 参数。

options
文档
可选。aggregate() 通过的其他选项
aggregate 命令。仅当您将 pipeline 指定为数组时才可用。

options 文档可包含以下字段和值:

5.0 版本中的更改

字段
类型
说明
explain
布尔

可选。指定返回有关管道处理的信息。有关示例,请参阅返回聚合管道操作的信息

不适用于多文档事务

allowDiskUse
布尔

可选。允许写入到临时文件。设置为 true 时,聚合操作可以将数据写入到 dbPath 目录中的 _tmp 子目录。示例参见allowDiskUseByDefault 交互

如果聚合阶段因为内存限制而写入临时文件,则分析器日志消息诊断日志消息包含一个 usedDisk 指示器。

cursor
文档
可选。指定游标的 初始批处理大小。cursor 字段的值是具有字段 batchSize 的文档。有关语法和示例,请参阅指定初始批处理大小
maxTimeMS
non-negative integer

可选。指定处理游标上操作的时间限制(以毫秒为单位)。默认值为 60000 毫秒或 60 秒。如果您明确将该值设置为 0,则操作不会超时。

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

bypassDocumentValidation
布尔

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

启用 db.collection.aggregate() 可在操作过程中绕过文档验证。这样就可以插入不符合验证要求的文档。

readConcern
文档

可选。指定读关注

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

可能的读关注级别是:

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

$out 阶段不能与读关注 "linearizable" 一起使用。如果为 db.collection.aggregate() 指定 "linearizable" 读关注,则不能将 $out 阶段包括在管道中。

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

文档

可选。

指定用于操作的排序规则

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

排序规则选项的语法如下:

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

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

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

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

您不能为一个操作指定多个排序规则。例如,您不能为每个字段指定不同的排序规则,或者如果执行带排序的查找,则不能使用一种排序规则进行查找而另一种排序规则进行排序。

hint
字符串或文档

可选。用于该聚合的索引。该索引位于运行聚合的初始集合/视图上。

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

注意

hint 不适用于 $lookup$graphLookup 阶段。

comment
字符串
可选。用户可以指定任意字符串来帮助通过数据库分析器、currentOp 和日志来跟踪操作。
writeConcern
文档

可选。一个表达写关注的文档,该写关注会与 $out$merge 阶段一起配合使用。

$out$merge 阶段省略使用默认写关注。

let
文档

可选。

指定包含变量列表的文档。这样可以将变量与查询文本分开,从而提高命令的可读性。

文档语法为:

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

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

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

要使用变量筛选管道 $match 阶段的结果,必须在 $expr 运算符中访问该变量。

有关使用 let 和变量的完整示例,请参阅let 中使用变量

版本 5.0 中的新增功能

如果出现错误,aggregate() 辅助程序会抛出异常。

mongosh中,如果从db.collection.aggregate()返回的游标未赋值给使用var关键字的变量,则mongosh会自动迭代游标最多20次。 有关在 mongosh 中处理游标的信息,请参阅mongosh中迭代游标

聚合返回的游标只支持对已评估游标进行操作的游标方法(即第一批已检索到的游标),如以下方法:

有关更多信息,请参阅:

对于在一个会话内创建的游标,不能在该会话外调用 getMore

同样,对于在会话外创建的游标,不能在会话内调用 getMore

MongoDB 驱动程序和 mongosh 将所有操作与服务器会话相关联,未确认的写入操作除外。对于未与会话显式关联的操作(即使用 Mongo.startSession()),MongoDB 驱动程序和 mongosh 会创建隐式会话并将其与该操作关联。

如果会话空闲时间超过 30 分钟,MongoDB Server 会将该会话标记为已过期,并可能随时将其关闭。当 MongoDB Server 关闭会话时,它还会终止任何正在进行的操作并打开与会话关联的游标。这包括使用超过 30 分钟的 noCursorTimeout()maxTimeMS() 配置的游标。

对于返回游标的操作,如果游标的空闲时间可能超过 30 分钟,则使用 Mongo.startSession() 在显式会话中发出操作,并使用 refreshSessions 命令定期刷新会话。更多信息,请参阅会话空闲超时

db.collection.aggregate() 可以在分布式事务中使用。

但是,事务中不允许有以下阶段:

此外,您不能指定 explain 选项。

  • 对于在 ACID 事务外部创建的游标,无法在 ACID 事务内部调用 getMore

  • 对于在事务中创建的游标,无法在事务外部调用 getMore

重要

在大多数情况下,与单文档写入操作相比,分布式事务会产生更高的性能成本,并且分布式事务的可用性不应取代有效的模式设计。在许多情况下,非规范化数据模型(嵌入式文档和数组)仍然是数据和使用案例的最佳选择。换言之,对于许多场景,适当的数据建模将最大限度地减少对分布式事务的需求。

有关其他事务使用注意事项(如运行时间限制和 oplog 大小限制),另请参阅生产注意事项

对于不包含 $out$merge 阶段的 db.collection.aggregate() 操作:

从 MongoDB 4.2 开始,如果在操作完成之前,发出 db.collection.aggregate() 的客户端断开连接,MongoDB 将使用killOpdb.collection.aggregate() 标记为终止。

以下示例使用包含以下文档的集合 orders

db.orders.insertMany( [
{ _id: 1, cust_id: "abc1", ord_date: ISODate("2012-11-02T17:04:11.102Z"), status: "A", amount: 50 },
{ _id: 2, cust_id: "xyz1", ord_date: ISODate("2013-10-01T17:04:11.102Z"), status: "A", amount: 100 },
{ _id: 3, cust_id: "xyz1", ord_date: ISODate("2013-10-12T17:04:11.102Z"), status: "D", amount: 25 },
{ _id: 4, cust_id: "xyz1", ord_date: ISODate("2013-10-11T17:04:11.102Z"), status: "D", amount: 125 },
{ _id: 5, cust_id: "abc1", ord_date: ISODate("2013-11-12T17:04:11.102Z"), status: "A", amount: 25 }
] )

以下聚合操作选择状态等于 "A" 的文档,按 cust_id 字段对匹配文档进行分组,并根据 amount 字段的总和计算每个 cust_id 字段的 total,并对结果按 total 字段降序排列:

db.orders.aggregate( [
{ $match: { status: "A" } },
{ $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
{ $sort: { total: -1 } }
] )

该操作返回一个包含以下文档的游标:

[
{ _id: "xyz1", total: 100 },
{ _id: "abc1", total: 75 }
]

mongosh 自动遍历返回的游标,以打印结果。请参阅mongosh 中遍历游标以在 mongosh 中手动处理游标。

以下示例使用 db.collection.explain() 查看聚合管道执行计划的详细信息。

db.orders.explain().aggregate( [
{ $match: { status: "A" } },
{ $group: { _id: "$cust_id", total: { $sum: "$amount" } } },
{ $sort: { total: -1 } }
] )

该操作返回一份详细说明聚合管道处理过程的文档。例如,除其他详细信息外,文档还可以显示该操作使用的索引(如果有)。[1] 如果 orders 集合是分片集合,则文档还会显示分片和合并操作之间的分工,以及针对特定查询的目标分片。

注意

explain 输出文档的目标读者是人类,而不是机器,并且输出格式因版本而不同。

您可以将 executionStatsallPlansExecution 解释模式传递给 db.collection.explain() 方法,以查看更详细的解释输出。

[1] 索引筛选器可能影响所用索引的选择。详情参见索引筛选器

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

单个 findaggregate 命令可以通过以下任一方式覆盖 allowDiskUseByDefault 参数:

  • 使用 { allowDiskUse: true } 以允许在 allowDiskUseByDefault 设置为 false 时将临时文件写入磁盘

  • 使用 { allowDiskUse: false } 以禁止在 allowDiskUseByDefault 设置为 true 时将临时文件写入磁盘

如果聚合阶段因为内存限制而写入临时文件,则分析器日志消息诊断日志消息包含一个 usedDisk 指示器。

有关更多信息,请参阅聚合管道限制。

要指定游标的初始批次大小,请对 cursor 选项使用以下语法:

cursor: { batchSize: <int> }

例如,以下聚合操作指定游标的初始批处理大小为 0

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 字段。

mongosh 自动遍历返回的游标,以打印结果。请参阅mongosh 中遍历游标以在 mongosh 中手动处理游标。

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

集合 restaurants 包含以下文档:

db.restaurants.insertMany( [
{ _id: 1, category: "café", status: "A" },
{ _id: 2, category: "cafe", status: "a" },
{ _id: 3, category: "cafE", status: "a" }
] )

下面的聚合操作包括排序规则选项:

db.restaurants.aggregate(
[ { $match: { status: "A" } }, { $group: { _id: "$category", count: { $sum: 1 } } } ],
{ collation: { locale: "fr", strength: 1 } }
);

注意

如果执行的聚合涉及多个视图,例如使用 $lookup$graphLookup ,则这些视图必须采用相同的排序规则

有关排序规则字段的说明,请参阅排序规则文档

使用以下文档创建集合 food

db.food.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.food.createIndex( { qty: 1, type: 1 } );
db.food.createIndex( { qty: 1, category: 1 } );

下面的聚合操作包含 hint 选项,强制使用指定的索引:

db.food.aggregate(
[ { $sort: { qty: 1 }}, { $match: { category: "cake", qty: 10 } }, { $sort: { type: -1 } } ],
{ hint: { qty: 1, category: 1 } }
)

使用 readConcern 选项指定操作的读关注。

您不能将 $out$merge 阶段与读关注 "linearizable" 一起使用。换言之,如果您为 db.collection.aggregate() 指定 "linearizable" 读关注,则不能在管道中包含任一阶段。

对副本集执行以下操作可以指定读关注 "majority",以读取确认已写入大多数节点的数据的最新副本。

注意

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

  • 您可以为包含 $out 阶段的聚合指定读关注级别 "majority"

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

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

名为 movies 的集合包含以下格式的文档:

db.movies.insertOne(
{
_id: ObjectId("599b3b54b8ffff5d1cd323d8"),
title: "Jaws",
year: 1975,
imdb: "tt0073195"
}
)

以下聚合操作可查找 1995 年制作的电影,并包含 comment 选项,以在 logsdb.system.profile 集合和 db.currentOp 中提供跟踪信息。

db.movies.aggregate( [ { $match: { year : 1995 } } ], { comment : "match_all_movies_from_1995" } ).pretty()

在启用了分析的系统上,您可以查询 system.profile 集合以查看所有最近的类似聚合,如下所示:

db.system.profile.find( { "command.aggregate": "movies", "command.comment" : "match_all_movies_from_1995" } ).sort( { ts : -1 } ).pretty()

这将以下列格式返回一组剖析器结果:

{
"op" : "command",
"ns" : "video.movies",
"command" : {
"aggregate" : "movies",
"pipeline" : [
{
"$match" : {
"year" : 1995
}
}
],
"comment" : "match_all_movies_from_1995",
"cursor" : {
},
"$db" : "video"
},
...
}

应用程序可以对注释中的任意信息进行编码,以便更轻松地跟踪或识别整个系统的特定操作。例如,应用程序可能会附加一个字符串注释,其中包含其进程 ID、线程 ID、客户端主机名和发出命令的用户。

版本 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.cakeSales.aggregate(
[
{ $match: {
$expr: { $gt: [ "$salesTotal", "$$targetTotal" ] }
} }
],
{ let: { targetTotal: 3000 } }
)

后退

集合