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

$ 群组 (聚合阶段)

$group

$group 阶段根据群组密钥将具有相同字段或表达式的多个文档合并为一个文档。结果是每个唯一的群组密钥对应一个文档。

A group key is often a field, or group of fields. The group key can also be the result of an expression. Use the _id field in the $group pipeline stage to set the group key. See below for usage examples.

在 $group 阶段输出中,_id 字段被设为该文档的组键。

The output documents can also contain additional fields that are set using accumulator expressions.

注意

$group does not order its output documents.

可以使用 $group 查找托管在以下环境中的部署:

  • MongoDB Atlas: The fully managed service for MongoDB deployments in the cloud

The $group stage has the following prototype form:

{
$group:
{
_id: <expression>, // Group key
<field1>: { <accumulator1> : <expression1> },
...
}
}
字段
说明

_id

Required. The _id expression specifies the group key. If you specify an _id value of null, or any other constant value, the $group stage returns a single document that aggregates values across all of the input documents. See the Group by Null example.

field

Optional. Computed using the accumulator operators.

The _id and the accumulator operators can accept any valid expression. For more information on expressions, see Expressions.

$group 是一个阻塞阶段,这会导致管道在处理数据前等待为阻塞阶段检索所有输入数据。阻塞阶段可能会降低性能,因为它会减少具有多个阶段的管道的并行处理。对于大型数据集,阻塞阶段还可能使用大量内存。

<accumulator> 操作符必须是以下累加器操作符之一:

名称
说明

返回用户定义的累加器函数的结果。

返回每个群组的唯一表达式值数组。未定义数组元素的排序。

返回数值的平均值。

根据指定的排序顺序返回组内的底部元素。

根据指定的排序顺序,返回群组内后 n 个字段的聚合。

返回组合了两个或多个数组元素的单个大量。

8.1版本新增。

返回群组中的文档数。

有别于 $count 管道阶段。

返回群组中第一个文档的表达式结果。

返回群组内前 n 个元素的聚合。仅当文档按定义的顺序排列时才有意义。与 $firstN 数组操作符不同。

返回群组中最后一份文档的表达式结果。

返回对组中最后 n 个元素评估指定表达式的结果。

返回每个群组的最大表达式值。

返回群组中 n 个最大值元素的聚合。与 $maxN 数组操作符不同。

返回组中文档的中位数(第 50 百分位数)值的近似值。

7.0版本新增。

返回通过组合每个组的输入文档创建的文档。

返回每个群组的最小表达式值。

返回组中 n 个最小值元素的聚合。与 $minN 数组操作符不同。

返回与指定的各百分位数一一对应的标量值数组。

7.0版本新增。

返回每组中文档的大量表达式值。

接受两个或多个数组,并返回一个数组,其中包含出现在每个输入数组中的元素。

8.1版本新增。

返回组中文档值的总体标准差。

返回组内文档值的示例标准差。

返回数值的总和。忽略非数字值。

根据指定的排序顺序返回群组内第一个元素。

根据指定的排序顺序,返回群组内前 n 个字段的聚合。

$group 阶段不能包含带有空字段名称的累加器表达式。有关详细信息,请参阅 空字段名称 $group 限制。

If the $group stage exceeds 100 megabytes of RAM, MongoDB writes data to temporary files. However, if the allowDiskUse option is set to false, $group returns an error. For more information, refer to aggregation pipeline limits.

This section describes optimizations to improve the performance of $group. There are optimizations that you can make manually and optimizations MongoDB makes internally.

If a pipeline sorts and groups by the same field and the $group stage only uses the $first or $last accumulator operator, consider adding an index on the grouped field which matches the sort order. In some cases, the $group stage can use the index to quickly find the first or last document of each group.

例子

如果 movies集合包含索引{ year: 1, title: 1 },则以下管道可以使用该索引来查找群组的第一个 document:

db.movies.aggregate([
{
$sort: { year: 1, title: 1 }
},
{
$group: {
_id: { year: "$year" },
title: { $first: "$title" }
}
}
])

Starting in version 5.2, MongoDB uses the slot-based execution query engine to execute $group stages if either:

  • $group 是管道中的第一个阶段。

  • 管道中的所有先前阶段也可以由基于槽位的执行引擎执行。

有关更多信息,请参阅 $group 优化。

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

The following aggregation operation uses the $group stage to count the number of documents in the movies collection:

db.movies.aggregate([
{
$group: {
_id: null,
count: { $count: {} }
}
}
])
[
{
_id: null,
count: 21349
}
]

这个聚合操作相当于以下 SQL 语句:

SELECT COUNT(*) AS count FROM movies

以下聚合操作使用 $group 阶段从 movies 集合中检索不同的 rated 值:

db.movies.aggregate( [ { $group : { _id : "$rated" } } ] )
[
{
_id: 'TV-PG'
},
{
_id: 'PG'
},
{
_id: 'TV-14'
},
{
_id: 'OPEN'
},
{
_id: 'Not Rated'
},
{
_id: 'GP'
},
{
_id: 'TV-Y7'
},
{
_id: 'G'
},
{
_id: 'PG-13'
},
{
_id: null
},
{
_id: 'M'
},
{
_id: 'R'
},
{
_id: 'TV-MA'
},
{
_id: 'APPROVED'
},
{
_id: 'PASSED'
},
{
_id: 'Approved'
},
{
_id: 'AO'
},
{
_id: 'TV-G'
}
]

注意

示例,以下形式的 $group 操作可能会产生 DISTINCT_SCAN:

{ $group : { _id : "$<field>" } }

有关检索非重复值行为的更多信息,请参阅非重复命令行为。

要查看操作是否会产生DISTINCT_SCAN ,请检查操作的解释结果。

以下聚合操作按 rated字段对document进行分组,计算每个评级的总运行时间,并仅返回总运行时间大于或等于 100000 的评级:

db.movies.aggregate(
[
// First Stage
{
$group: {
_id: "$rated",
totalRuntime: { $sum: "$runtime" }
}
},
// Second Stage
{
$match: { "totalRuntime": { $gte: 100000 } }
}
]
)
[
{
_id: 'PG-13',
totalRuntime: 250843
},
{
_id: 'R',
totalRuntime: 582318
},
{
_id: null,
totalRuntime: 967127
},
{
_id: 'PG',
totalRuntime: 191204
}
]
第一个阶段:
The $group stage groups the documents by rated to retrieve the distinct rating values. This stage returns the totalRuntime for each rating group.
第二个阶段:
$match 阶段筛选生成的 document,仅返回 totalRuntime 大于或等于 100000 的评分。

这个聚合操作相当于以下 SQL 语句:

SELECT rated,
Sum(runtime) AS totalRuntime
FROM movies
GROUP BY rated
HAVING totalRuntime >= 100000

提示

$match

以下管道计算 1910之前每年的总运行时间、平均运行时间和电影数量:

db.movies.aggregate([
{ $match: { "year": { $lt: 1910 } } },
{
$group: {
_id: "$year",
totalRuntime: { $sum: "$runtime" },
averageRuntime: { $avg: "$runtime" },
count: { $sum: 1 }
}
},
{ $sort: { totalRuntime: -1 } }
])
[
{ _id: 1909, totalRuntime: 14, averageRuntime: 14, count: 1 },
{ _id: 1903, totalRuntime: 11, averageRuntime: 11, count: 1 },
{ _id: 1896, totalRuntime: 2, averageRuntime: 1, count: 2 }
]
第一个阶段:
$match 阶段会筛选 document,仅将 1910 之前发布的电影传递到下一阶段。
第二个阶段:
The $group stage groups the documents by year and calculates the total runtime, average runtime, and total count of the documents in each group.
第三个阶段:
$sort 阶段按群组的总运行时间对结果进行降序排序。

这个聚合操作相当于以下 SQL 语句:

SELECT year,
Sum(runtime) AS totalRuntime,
Avg(runtime) AS averageRuntime,
Count(*) AS count
FROM movies
WHERE year < 1910
GROUP BY year
ORDER BY totalRuntime DESC

提示

以下聚合操作指定 null 的 _id群组,计算集合中所有 document 的总运行时间、平均运行时间和计数。

db.movies.aggregate([
{
$group: {
_id: null,
totalRuntime: { $sum: "$runtime" },
averageRuntime: { $avg: "$runtime" },
count: { $sum: 1 }
}
}
])
[
{
_id: null,
totalRuntime: 2167458,
averageRuntime: 103.65652797704448,
count: 21349
}
]

这个聚合操作相当于以下 SQL 语句:

SELECT Sum(runtime) AS totalRuntime,
Avg(runtime) AS averageRuntime,
Count(*) AS count
FROM movies

提示

以下聚合操作对 movies集合中的数据进行透视,以按年份对书名进行群组:

db.movies.aggregate([
{ $match: { year: { $lt: 1910 } } },
{ $group: { _id: "$year", titles: { $push: "$title" } } },
{ $sort: { _id: 1 } }
])
[
{ _id: 1896, titles: [ 'The Kiss', 'The Kiss' ] },
{ _id: 1903, titles: [ 'The Great Train Robbery' ] },
{ _id: 1909, titles: [ 'A Corner in Wheat' ] }
]

以下聚合操作按年份对document进行分组:

db.movies.aggregate([
{ $match: { year: { $lt: 1910 } } },
{ $group: { _id: "$year", movies: { $push: "$$ROOT" } } },
{
$addFields: {
totalRuntime: { $sum: "$movies.runtime" }
}
},
{ $sort: { _id: 1 } }
])
[
{ _id: 1896, movies: '...', totalRuntime: 2 },
{ _id: 1903, movies: '...', totalRuntime: 11 },
{ _id: 1909, movies: '...', totalRuntime: 14 }
]
第一个阶段:
$match filters the document,仅将 1910之前发布的电影传递到下一阶段。
第二个阶段:
$group uses the $$ROOT system variable to group the entire documents by year.
第三个阶段:

$addFields 在输出中添加一个字段,其中包含每年的电影总放映时间。

注意

生成的文档不得超过 16 MiB 的 BSON 文档大小限制。

第四阶段:
$sort 按 _id 升序对生成的 document 进行排序。

The Group and Total Data tutorial provides an extensive example of the $group operator in a common use case.

要学习;了解有关相关管道阶段的更多信息,请参阅 $addFields 指南。

获得技能徽章

免费掌握“数据转换基础”!

了解详情

给本页内容打分