Docs 菜单

Docs 主页开发应用程序MongoDB Manual

db.collection.aggregate()

在此页面上

  • 定义
  • 兼容性
  • 语法
  • 行为
  • 举例
db.collection.aggregate(pipeline, options)

重要

mongosh 方法

本页介绍了 mongosh方法。这不是数据库命令或特定语言驱动程序(例如 Node.js)的文档。

有关数据库命令,请参阅 aggregate 命令。

对于 MongoDB API 驱动程序,请参阅特定语言的MongoDB 驱动程序文档。

对于传统 mongo Shell 文档,请参阅相应 MongoDB Server 版本的文档:

mongo shell v4.4

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

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

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

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

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

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

范围
类型
说明
pipeline
阵列

一系列数据聚合操作或阶段。 See the aggregation pipeline operators for details.

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

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

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

5.0 版本中的更改

字段
类型
说明
explain
布尔

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

不适用于多文档事务

allowDiskUse
布尔

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

如果任何聚合阶段由于 内存限制 而将数据写入临时文件,则 分析器日志消息 和 诊断日志消息 会包含 指示符。usedDisk

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

可选。指定处理游标上操作的时间限制(以毫秒为单位)。如果您没有指定 maxTimeMS 的值,操作将不会超时。如果值为 0,则明确指定默认的无限制行为。

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

bypassDocumentValidation
布尔

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

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

readConcern
文档

可选。指定读关注

从 MongoDB 3.6 开始,readConcern 选项具有以下事务语法: readConcern: { level: <value> }

可能的读关注级别是:

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

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

$merge阶段不能与读关注"linearizable" 一起使用。也就是说,如果您为"linearizable" db.collection.aggregate()指定$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 大小限制),另请参阅生产注意事项

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

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

以下示例使用包含以下文档的集合 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 MB 以上内存容量的管道阶段默认将临时文件写入磁盘。在 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" 结合使用。也就是说,如果您为"linearizable" db.collection.aggregate()指定 读关注,则不能在管道中包含任一阶段。

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

注意

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

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

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

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 } }
)
← 集合方法