$group简介:按指定的标识符表达式对输入文档进行分组,并将累加器表达式(如果指定)应用到每个组。使用所有输入文档,并为每个不同的组输出一个文档。输出文档只包含标识符字段,如果指定,则包含累积字段。
$group语法:
{
$group:
{
_id: <expression>, // Group By Expression
<field1>: { <accumulator1> : <expression1> },
...
}
}
# _id 必需的。如果您指定_id值为null,或任何其他常量值,$group阶段计算所有输入文档作为一个整体的累积值。
# field1 可选的参数。使用累加器操作符。
$group注意点:
$group
的输出文档不排序。$group
阶段的读写限制为100兆字节。默认情况下,如果阶段超过这个限制,$group返回一个错误。要为阶段处理提供更多空间,可以使用allowDiskUse选项来允许聚合管道阶段将数据写入临时文件。
$group累加器操作符(accumulator Operator):
操作符 | 描述 |
---|---|
$accumulator | 返回用户定义的累加器函数的结果。 |
$addToSet | 返回每个组的唯一表达式值数组。数组元素的顺序未定义。 |
$avg | 返回数值的平均值。忽略了非数字值。 |
$count | 返回每个组中文档的数量。 |
$first | 返回每个组的第一个文档的值。只有在文档已排序的情况下才定义顺序。 |
$last | 为每个组返回最后一个文档中的值。只有在文档已排序的情况下才定义顺序。 |
$max | 返回每个组的最大的表达式值。 |
$mergeObjects | 返回通过组合每个组的输入文档创建的文档。 |
$min | 返回每个组的最小表达式值。 |
$push | 返回每个组中文档的表达式值数组。 |
$stdDevPop | 返回输入值的总体标准偏差。 |
$stdDevSamp | 返回输入值的样本标准差。 |
$sum | 返回数值的和。忽略了非数字值。 |
$group的基本操作示例:
# 插入测试数据
db.col01.insertMany(
[
{name:'doc01',age:12,status:'open',permissions:['insert'],son:{name:'a', age:11}, createTime: new Date()},
{name:'doc02',age:23,status:'open',permissions:['insert'],son:{name:'b', age:12}, createTime: new Date()},
{name:'doc02',age:34,status:'open',permissions:['insert'],son:{name:'c'}, createTime: new Date()},
{name:'doc03',age:56,status:'open',permissions:['insert'],son:{name:'d', age:13}, createTime: new Date()},
{name:'doc03',age:67,status:'open',permissions:['insert'],son:{name:'e'}, createTime: new Date()},
{name:'doc04',age:78,status:'close',permissions:['insert'],son:{name:'f', age:14}, createTime: new Date()},
{name:'doc05',age:89,status:'close',permissions:['insert'],son:{name:'g'}, createTime: new Date()}
]
, {})
# $group指定_id为null
mymongo> db.col01.aggregate({$group:{_id: null, count:{$count: {}}}})
[ { _id: null, count: 7 } ]
# $group对name进行分组 类似于SQL:select name from col01 group by name
mymongo> db.col01.aggregate({$group:{_id: "$name"}})
[
{ _id: 'doc02' },
{ _id: 'doc03' },
{ _id: 'doc01' },
{ _id: 'doc05' },
{ _id: 'doc04' }
]
# $group对name进行分组$count计数 类似于SQL:select name, count(*) as count from col01 group by name
mymongo> db.col01.aggregate({$group:{_id: "$name", count:{$count: {}}}})
[
{ _id: 'doc02', count: 2 },
{ _id: 'doc03', count: 2 },
{ _id: 'doc01', count: 1 },
{ _id: 'doc05', count: 1 },
{ _id: 'doc04', count: 1 }
]
# 使用$group对name进行分组并$sum求和 类似于SQL:select name, sum(age) as count from col01 group by name
mymongo> db.col01.aggregate({$group:{_id: "$name", sumAge:{$sum: "$age"}}})
[
{ _id: 'doc02', sumAge: 57 },
{ _id: 'doc03', sumAge: 123 },
{ _id: 'doc04', sumAge: 78 },
{ _id: 'doc05', sumAge: 89 },
{ _id: 'doc01', sumAge: 12 }
]
# $group对name进行分组$max返回组内最大的age 类似于SQL:select name, max(age) as count from col01 group by name
mymongo> db.col01.aggregate({$group:{_id: "$name", sumMax:{$max: "$age"}}})
[
{ _id: 'doc02', sumMax: 34 },
{ _id: 'doc03', sumMax: 67 },
{ _id: 'doc04', sumMax: 78 },
{ _id: 'doc05', sumMax: 89 },
{ _id: 'doc01', sumMax: 12 }
]
# $push返回每个组中文档的表达式值数组。
ongo> db.col01.aggregate({$group:{_id: "$name", ages:{$push: "$age"} }})
[
{ _id: 'doc02', ages: [ 23, 34 ] },
{ _id: 'doc03', ages: [ 56, 67 ] },
{ _id: 'doc04', ages: [ 78 ] },
{ _id: 'doc05', ages: [ 89 ] },
{ _id: 'doc01', ages: [ 12 ] }
]
# $addToSet返回每个组中文档的表达式值数组并去重。
mymongo> db.col01.aggregate({$group:{_id: "$name", ages:{$addToSet: "$age"} }})
[
{ _id: 'doc02', ages: [ 23, 34 ] },
{ _id: 'doc03', ages: [ 67, 56 ] },
{ _id: 'doc04', ages: [ 78 ] },
{ _id: 'doc05', ages: [ 89 ] },
{ _id: 'doc01', ages: [ 12 ] }
]
# $mergeObjects合并一个组内的子对象
db.col01.aggregate({$group:{_id: "$name", mergeSon:{$mergeObjects: "$son"}}})
[
{ _id: 'doc02', mergeSon: { name: 'c', age: 12 } },
{ _id: 'doc03', mergeSon: { name: 'e', age: 13 } },
{ _id: 'doc04', mergeSon: { name: 'f', age: 14 } },
{ _id: 'doc05', mergeSon: { name: 'g' } },
{ _id: 'doc01', mergeSon: { name: 'a', age: 11 } }
]
# $stdDevPop
mymongo> db.col01.aggregate({$group: {_id: "$name", ageStdDevPop:{$stdDevPop:"$age"}}})
[
{ _id: 'doc02', ageStdDevPop: 5.5 },
{ _id: 'doc03', ageStdDevPop: 5.5 },
{ _id: 'doc04', ageStdDevPop: 0 },
{ _id: 'doc05', ageStdDevPop: 0 },
{ _id: 'doc01', ageStdDevPop: 0 }
]
# $stdDevSamp
mymongo> db.col01.aggregate({$group: {_id: "$name", ageStdDevSamp:{$stdDevSamp:"$age"}}})
[
{ _id: 'doc02', ageStdDevSamp: 7.7781745930520225 },
{ _id: 'doc03', ageStdDevSamp: 7.7781745930520225 },
{ _id: 'doc04', ageStdDevSamp: null },
{ _id: 'doc05', ageStdDevSamp: null },
{ _id: 'doc01', ageStdDevSamp: null }
]
# $group的分组参数_id使用表达式
mymongo> db.col01.aggregate({$group:{_id:{$dateToString:{format:"%Y-%m-%d",date:"$createTime"}},count:{$count:{}}}})
[ { _id: '2021-12-06', count: 7 } ]