对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。

聚合(数据库命令)

aggregate

使用 聚合管道执行聚合操作。管道可以让您通过一系列阶段处理来自集合或其他来源的数据。

提示

在 mongosh 中,此命令也可通过 db.aggregate() 和 db.collection.aggregate() 辅助方法或 watch() 辅助方法来运行。

辅助方法对 mongosh 用户来说很方便,但它们返回的信息级别可能与数据库命令不同。如果不追求方便或需要额外的返回字段,请使用数据库命令。

此命令可用于以下环境中托管的部署:

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

重要

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

在版本5.0中进行了更改。

该命令具有以下语法:

db.runCommand( { aggregate: "<collection>" || 1, pipeline: [ <stage>, <...> ], explain: <boolean>, allowDiskUse: <boolean>, allowPartialResults: <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 querySettings: <document> // Added in MongoDB 9.0 })

aggregate 命令将以下字段作为参数:

字段
类型
说明

aggregate

字符串

充当聚合管道的输入的集合或视图的名称。使用 1 执行与集合无关的命令。

pipeline

阵列

聚合管道阶段数组,作为聚合管道的一部分处理和转换文档流。

explain

布尔

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

不适用于多文档事务。

allowDiskUse

布尔

可选。

使用此选项可以覆盖特定查询的 allowDiskUseByDefault。您可以使用此选项执行以下任一操作:

  • 禁止在默认允许使用磁盘的系统上使用磁盘。

  • 支持在默认情况下禁止使用磁盘的系统上使用磁盘。

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

有关详细信息,请参阅allowDiskUseByDefault。

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

allowPartialResults

布尔

可选。对于通过 mongos 针对分片集合运行的聚合,当一个或多个查询的分片不可用时,该命令可以返回部分结果,而不是错误。后续 getMore 命令也可以返回部分结果。默认为 false,如果查询的分片不可用,则返回错误。

仅在初始 aggregate 命令上设置 allowPartialResults。您无法在 getMore 上设置它,但每个 getMore 都会从游标继承该设置。

由于分片可能会在任何点变为不可用状态,部分结果可能会出现在初始 aggregate 响应中、在后续 getMore 响应中,或两者兼而有之。当批处理从不可用分片中忽略结果时,该批处理的响应包含 partialResultsReturned: true 字段。当所有查询的分片都可用于批处理时,响应会省略 partialResultsReturned。partialResultsReturned 可以仅包含来自可用分片的文档。当 partialResultsReturned 为 true 时,请勿假设结果集已完成。

如果管道满足以下条件,该命令将返回 InvalidOptions 错误:

  • 以写入阶段结束,例如 $out 或 $merge。

  • 是一个 变更流 聚合。

  • 包含一个 Atlas Search 阶段,例如 $search、$vectorSearch、$rankFusion 或 $scoreFusion。

cursor

文档

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

您必须使用带有 cursor 选项的 aggregate 命令,除非该命令包含 explain 选项。

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

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

maxTimeMS

non-negative integer

可选。

指定时间限制(以毫秒为单位)。如果您未指定 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

字符串或文档

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

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

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

comment

any

可选。用户提供的待附加到该命令的注释。设置后,该注释将与该命令的记录一起出现在以下位置:

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

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

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 中的新增功能。

querySettings

文档

可选。仅应用于此命令执行的查询设置。querySettings 文档接受以下字段:

  • indexHints

  • queryFramework

  • reject

  • comment

  • queryKnobs

  • maxTimeMS

有关这些字段的说明,请参阅 命令字段。

MongoDB 不会在集群上存储这些设置,这些设置也不应用于具有相同 查询结构 的其他查询。要为查询结构设置持久有效的查询设置,请使用 setQuerySettings。

MongoDB 会将您在命令中传递的设置与集群上为同一查询结构存储的任何查询设置相结合。如果两个设置指定了同一个字段,则以存储的集群设置为准。

9.0版本新增。

您必须使用带有 cursor 选项的 aggregate 命令,除非该命令包含 explain 选项。

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

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

有关聚合管道的更多信息,请参阅:

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

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

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

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

如果游标可能空闲超过 30 分钟,请使用 Mongo.startSession() 在显式会话中发出操作。使用 refreshSessions 命令定期刷新会话。有关详细信息,请参阅会话空闲超时。

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

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

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

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

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

重要

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

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

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

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

8.0版本新增。

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

在查询规划期间,查询优化器将使用查询设置作为附加输入,这样会影响为运行查询而选择的计划。您还可以使用查询设置来阻塞查询结构。

要添加查询设置并探索示例,请参阅 setQuerySettings。

您可以为 find、distinct 和 aggregate 命令添加查询设置。

查询设置具有更多功能,相比已弃用的索引过滤器而言是您的首选。

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

使用 Stable API V1 时,支持 aggregate 命令,但有以下例外:

您必须使用带有 cursor 选项的 aggregate 命令,除非该命令包含 explain 选项。

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

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

大多数用户应该使用aggregatedb.collection.aggregate() mongosh提供的 辅助工具或驱动程序中的等效辅助工具,而不是直接运行 命令。

除演示命令语法的前两个示例外,本页中的示例均使用 db.collection.aggregate() 辅助工具/辅助程序。

本页上的示例使用来自 sample_mflix 数据集的数据。有关如何将此数据集加载到您的自管理 MongoDB 部署中的详细信息,请参阅 加载示例数据集。如果您对示例数据库进行了任何修改,您可能需要删除并重新创建数据库,才能运行此页面上的示例。

sample_mflix数据库中的 movies集合包含如下document:

注意

movies集合中的document包含此处未显示的其他字段。

{ title: 'The Shawshank Redemption', year: 1994, genres: [ 'Crime', 'Drama' ], runtime: 142, imdb: { rating: 9.3, votes: 1521105, id: 111161 }, directors: [ 'Frank Darabont' ], cast: [ 'Tim Robbins', 'Morgan Freeman', 'Bob Gunton', 'William Sadler' ],},{ title: 'The Godfather', year: 1972, genres: [ 'Crime', 'Drama' ], runtime: 175, imdb: { rating: 9.2, votes: 1038358, id: 68646 }, directors: [ 'Francis Ford Coppola' ], cast: [ 'Marlon Brando', 'Al Pacino', 'James Caan', 'Richard S. Castellano' ]},{ title: 'Pulp Fiction', year: 1994, genres: [ 'Crime', 'Drama' ], runtime: 154, imdb: { rating: 8.9, votes: 1179033, id: 110912 }, directors: [ 'Quentin Tarantino' ], cast: [ 'Tim Roth', 'Amanda Plummer', 'Laura Lovelace', 'John Travolta' ]},{ title: 'Forrest Gump', year: 1994, genres: [ 'Drama', 'Romance' ], runtime: 142, imdb: { rating: 8.8, votes: 1087227, id: 109830 }, directors: [ 'Robert Zemeckis' ], cast: [ 'Tom Hanks', 'Rebecca Williams', 'Sally Field', 'Michael Conner Humphreys' ],},{ title: 'Inception', year: 2010, genres: [ 'Action', 'Sci-Fi', 'Thriller' ], runtime: 148, imdb: { rating: 8.8, votes: 1294646, id: 1375666 }, directors: [ 'Christopher Nolan' ], cast: [ 'Leonardo DiCaprio', 'Joseph Gordon-Levitt', 'Ellen Page', 'Tom Hardy' ],}

以下示例聚合 movies 集合以计算每个不同类型的数量:

db.runCommand( { aggregate: "movies", pipeline: [ { $project: { genres: 1 } }, { $unwind: "$genres" }, { $group: { _id: "$genres", count: { $sum : 1 } } } ], cursor: { }} )

在 mongosh 中,使用 db.collection.aggregate() 辅助工具运行相同的聚合:

db.movies.aggregate( [ { $project: { genres: 1 } }, { $unwind: "$genres" }, { $group: { _id: "$genres", 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.comments.aggregate( [ { $match: { date: { $gte: ISODate("2015-01-01") } } }, { $group: { _id: "$movie_id", commentCount: { $sum: 1 } } }, { $sort: { commentCount: -1 } } ], { explain: true })

注意

解释输出可能因版本而异。

默认下,需要超过 100 MB 内存才能执行的管道阶段会将临时文件写入磁盘。这些临时文件在管道执行期间持续存在,并且可能影响实例上的存储空间。

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

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

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

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

要设置初始批处理大小,请在 cursor 字段中包含 batchSize:

db.theaters.aggregate( [ { $match: { "location.address.state": "NY" } }, { $group: { _id: "$location.address.city", theaterCount: { $sum: 1 } } }, { $sort: { theaterCount: -1 } }, { $limit: 2 } ], { cursor: { batchSize: 0 } })

{ cursor: { batchSize: 0 } } 文档指定初始批处理大小,并表示首次批处理为空。这可以快速返回游标或失败消息,无需执行大量服务器端工作。

要为后续 getMore 操作指定批处理大小,请在 mongosh 中使用 batchSize(),或在 getMore 命令中使用 batchSize 字段。

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

以下聚合操作返回 sample_mflix数据库的 movies集合中所有法国电影的标题,并指定 fr 排序规则:

db.movies.aggregate( [ { $match: {"countries": "France", "languages": "French"} }, { $project: { "title": 1, "_id": 0 } } ], { collation: { locale: "fr", strength: 1 } })

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

sample_mflix数据库中的 movies集合包含与以下类似的document:

{ title: "The Shawshank Redemption", year: 1994, rated: "R", imdb: { rating: 9.3, votes: 1513145, id: 111161 }},{ title: "The Godfather", year: 1972, rated: "R", imdb: { rating: 9.2, votes: 1038358, id: 68646 }},{ title: "The Dark Knight", year: 2008, rated: "PG-13", imdb: { rating: 9, votes: 1495351, id: 468569 }},{ title: "Forrest Gump", year: 1994, rated: "PG-13", imdb: { rating: 8.8, votes: 1087227, id: 109830 }}

假设 movies集合上存在以下索引:

db.movies.createIndex( { "imdb.rating": 1, year: 1 } )
db.movies.createIndex( { "imdb.rating": 1, rated: 1 } )

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

db.movies.aggregate( [ { $sort: { "imdb.rating": 1 } }, { $match: { rated: "R", "imdb.rating": { $gte: 9.0 } } }, { $sort: { year: -1 } } ], { hint: { "imdb.rating": 1, rated: 1 } })

若要覆盖默认的读关注级别,请使用 readConcern 选项。getMore 命令使用原始 aggregate 命令中指定的 readConcern 级别。

movies对sample_mflix 数据库中的 集合的以下操作指定了 读关注(read concern) 的 "majority" ,以读取已确认已写入大多数节点的数据的最新副本。

重要

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

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

db.movies.aggregate( [ { $match: { "imdb.rating": { $gte: 8.0 } } }, { $group: { _id: "$rated", avgRating: { $avg: "$imdb.rating" }, count: { $sum: 1 } } }, { $sort: { avgRating: -1 } } ], { readConcern: { level: "majority" } })

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

要定义可在命令中其他位置访问的变量,请使用let选项。

注意

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

sample_mflix数据库中的 movies集合包含如下document:

{ title: "The Shawshank Redemption", year: 1994, rated: "R", imdb: { rating: 9.3, votes: 1513145, id: 111161 }, runtime: 142}

以下示例使用 let 选项为管道定义变量。该示例查找评分高且运行时间长的电影:

db.runCommand( { aggregate: "movies", pipeline: [ { $match: { $expr: { $and: [ { $gte: [ "$imdb.rating", "$$minRating" ] }, { $gte: [ "$runtime", "$$minRuntime" ] } ] } } }, { $project: { title: 1, year: 1, "imdb.rating": 1, runtime: 1 } }, { $sort: { "imdb.rating": -1 } }, { $limit: 3 } ], cursor: {}, let: { minRating: 8.5, minRuntime: 120 }} )