mongodb aggregate聚合管道

官网上的例子

MongoDB的聚合框架是基于数据处理管道的概念建模的。文档进入一个多阶段管道,该管道将文档转换为聚合的结果。例如:
在这里插入图片描述
在这个例子中:

db.orders.aggregate([
   { $match: { status: "A" } },
   { $group: { _id: "$cust_id", total: { $sum: "$amount" } } }
])
  • 第一阶段:$match阶段根据状态字段过滤文档,并将状态等于“A”的文档传递给下一阶段。
  • 第二阶段:$group阶段根据cust_id字段对文档进行分组,以计算每个惟一cust_id的金额总和。

最基本的管道阶段提供了类似查询和文档转换的过滤器,用于修改输出文档的形式。

其他管道操作提供了按特定字段对文档进行分组和排序的工具,还提供了聚合数组(包括文档数组)内容的工具。此外,管道阶段可以为计算平均值或连接字符串等任务使用操作符。

该管道使用MongoDB中的本地操作提供了高效的数据聚合,是MongoDB中数据聚合的首选方法。

aggregate 类似于 shell 脚本的管道,上条命令的输出等于下条命令的输入。
下面通过实际操作来熟悉 aggregate 。


数据准备

随便填的数据,mongodb版本4.x

订单表
db.orders.insertOne( { order_id: 'T00001', name: '苹果', price: 10, status: '正在运输', list: [1,2]} )
db.orders.insertOne( { order_id: 'T00001', name: '香蕉', price: 8, status: '正在运输', list: [1,2]} )
db.orders.insertOne( { order_id: 'T00002', name: '脐橙', price: 12, status: '已关闭', list: [1,2]} )
db.orders.insertOne( { order_id: 'T00002', name: '葡萄', price: 20, status: '已关闭', list: [1,2]} )
db.orders.insertOne( { order_id: 'T00003', name: '火龙果', price: 10, status: '正在运输', list: [1,2]} )
db.orders.insertOne( { order_id: 'T00003', name: '草莓', price: 15, status: '正在运输', list: [1,2]} )
db.orders.insertOne( { order_id: 'T00003', name: '西瓜', price: 25, status: '正在运输', list: [1,2]} )

用户表
db.user.insertOne( { username: 'zlfan', phone: '12345678941', address: 'xx地址', order_id: 'T00001'} )
db.user.insertOne( { username: 'zlfan', phone: '12345678941', address: 'xx地址', order_id: 'T00002'} )
db.user.insertOne( { username: 'zlfan', phone: '12345678941', address: 'xx地址', order_id: 'T00003'} )

实战

$project操作符

与 find() 的第二个参数作用相同,投影指定的列,还可以增加、删除、重命名字段

db.orders.aggregate([{ $project: { _id: 0, name: 1, price: 1 } }]);

在这里插入图片描述

$match操作符

用于过滤数据,只有满足条件的文档才能进入下一阶段。$match使用MongoDB的标准查询操作。
如查询价格大于10的文档

db.orders.aggregate([
  { $project: { _id: 0, name: 1, price: 1 } },
  { $match: { price: { $gt: 10 } } },
])

在这里插入图片描述

$limit操作符

用来限制返回的文档数量

db.orders.aggregate([
    { $project: { _id: 0, name: 1, price: 1 } },
    { $limit: 5 }
])

在这里插入图片描述

$skip操作符

跳过指定的文档数返回文档
如查询第二条文档后面的所有文档

db.orders.aggregate([
  { $project: { _id: 0, name: 1, price: 1 } },
  { $skip: 2 },
]);

在这里插入图片描述
在这里插入图片描述

$sort操作符

对于一个或多个要排序的字段,设置排序顺序为1或-1,分别指定升序或降序排序

db.orders.aggregate([
    { $project: { _id: 0, name: 1, price: 1 } },
    { $sort: { price: 1 } },
]);

在这里插入图片描述

重点:$group操作符

将集合中的文档分组,可用于统计结果。通过指定的_id表达式对输入文档进行分组,对于每个不同的分组,输出一个文档。每个输出文档的_id字段包含唯一的按值分组。输出文档还可以包含保存某些累加器表达式值的计算字段。

例:根据订单id分组,并统计出总金额,结果显示订单id和总金额

db.orders.aggregate([
  { $project: { _id: 0, order_id: 1,  price: 1 } },
  { $group: { _id: '$order_id', totalPrice: {$sum: '$price'} } },
]);

在这里插入图片描述
下表是一些常用聚合操作符

表达式说明关键代码
$sum计算总和{ $group: { _id: '$order_id', sum: {$sum: '$price'} } },
$avg计算平均值{ $group: { _id: '$order_id', avg: {$avg: '$price'} } }
$min获取集合中所有文档对应值得最小值{ $group: { _id: '$order_id', min: {$min: '$price'} } }
$max获取集合中所有文档对应值得最大值{ $group: { _id: '$order_id', max: {$max: '$price'} } }
$push在结果文档中插入值到一个数组中{ $group: { _id: '$order_id', goods: { $push: { name: '$name', price: '$price' } } } }
$addToSet在结果文档中插入值到一个数组中,但不创建副本{ $group: { _id: '$order_id', goods: { $addToSet : { name: '$name', price: '$price' } } } }
$first根据资源文档的排序获取第一个文档数据{ $group: { _id: "$order_id", firstName: { $first: "$name" } } }
$last根据资源文档的排序获取最后一个文档数据{ $group: { _id: "$order_id", lastName: { $last: "$name" } } }

重点:$lookup操作符

多表关联查询。
对同一数据库的非分片集合进行左外连接,从以已连接的集合中筛选文档。对于每个输入文档,$lookup阶段添加一个新的数组字段,它的元素来自连接集合的匹配文档。

例子:订单表左外连接用户表,显示商品名称,价格,用户名,用户电话

db.orders.aggregate([
  {
      $lookup: {
        from: 'user',				## 来自哪个集合(表)
        localField: 'order_id',		## 主集合(表)用以连接的字段
        foreignField: 'order_id',	## 要连接表的字段
        as: 'user'					## user将作为新的数组字段,加入主集合(表)
      }
  },
  { $project: { _id:0, name: 1, price: 1, 'user.username':1, 'user.phone': 1 } }
]);

在这里插入图片描述
更多聚合管道操作符:https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值