MongoDB Aggregation pipelines(聚合管道)之 $group

本文详细介绍了MongoDB的$group阶段,如何通过_expression_对文档分组,以及如何使用累加器操作符如$sum, $avg等计算聚合结果。实例演示了从年龄、权限和状态角度对文档进行分组和计数。
摘要由CSDN通过智能技术生成

$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 } ]

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值