MongoDB Shell 基本命令(三)聚合管道

  1. 管道含义

    类似Linux中的管道,前一个命令的输出作为后一个命令的输入。

  2. 显示网络连接、路由表和网络接口统计信息

json 复制代码
netstat -ano
-netstat:network statistics 网络统计
-a:显示所有连接和监听端口,包括所有活动的TCP和UDP连接。
-n:以数字形式显示地址和端口号,而不是尝试解析为主机名和服务名称。
-o:显示与每个连接关联的进程ID(PID),这使得用户可以知道哪个进程正在使用特定的网络连接。

加上管道,查看与某个特定端口(27017)相关的连接,findstr相当于Linux中的grep,用于查找字符串的命令行工具。

json 复制代码
netstat -ano | findstr :27017

"ESTABLISHED" 是 TCP 协议的一种状态,表示一条 TCP连接已经成功建立,并且可以开始数据通信。

加上管道,只查看LISTENING相关连接

json 复制代码
netstat -ano | findstr :27017 | findstr :27017 | findstr LISTENING

所以,管道的含义就是:前一个命令的结果,作为后续命令的输入。我们可以在前面查询的基础上,整理过后,再进行查询。

复制代码
select count(*) from tabname where ...;
select sum() from tabname group by ...;先分组再统计,相当于是多步操作
  1. count()和distinct()
json 复制代码
use cqust;
//如果查询条件为空,查询文档记录数
db.students.count();//集合的文档总数

//统计女生/男生的数量
var 查询条件={gender:0};
db.students.count(查询条件);

//第二种写法
db.students.find(查询条件).count()//count(查询条件)等价于find(查询条件).count()

//select distinct major from tbname
//distinct,获取不重复的取值
//查询2022级有哪些专业
var 查询条件={grade:2022};
var 返回字段={_id:0,major:1,grde:1};
db.students.find(查询条件,返回字段);//有重复值

//格式:db.students.distinct(取值字段,查询条件)
db.students.distinct("major",查询条件);//返回数组

//2022级学生上了哪些课程
db.students.distinct("courses.course",{grade:2022});

//一共有哪些课程
db.students.distinct("courses.course");
  1. 聚合管道
  • 聚合是数据处理和分析的过程,对来自多个文档的数据进行计算、总结和分析,强调数据的汇总和计算。

  • 管道是一个结构,通过多个处理阶段(每个阶段可以执行不同类型的操作)来实现聚合的过程。

  • 分组操作用到聚合管道。

  • $match:过滤输入文档,只有满足指定条件的文档会被传递到管道的下一个阶段。where(sql)

  • $group:将输入文档分组,并按指定的键对每个组编制汇总。可以计算总和、平均值等。

  • $sort:对输入文档进行排序。1、0升序和降序;

  • $project:重塑输入文档,选择需要的字段并可以添加计算字段。(字段名修改、增加字段)

  • limit和skip:用于限制返回的结果数量或跳过指定数量的文档。

第一阶段$match阶段按status字段过滤文档,并将status等于"A"的文档传递到下一阶段。

第二阶段$group阶段按cust_id字段将文档分组,以计算每个cust_id唯一值的金额总和。

$match 的含义- 功能 : $match 阶段用于过滤集合中的文档,以保留所有符合指定条件的文档。它的作用类似于 SQL 中的 WHERE 子句。

  • 聚合管道格式
json 复制代码
db.orders.aggregate([
    { $match: { status: "A" } },
    { $group: { _id: "$cust_id", total: { $sum: "$amount" } } }
])
//var 步骤1={步骤操作符:操作文档}
//var 步骤数组=[步骤1,步骤2,步骤3,...]
//db.集合名.aggregate(步骤数组)
{$group:{_id:分组字段,聚合字段:{$统计操作:$值字段}}}
{$project:{field1:1,newfield2:$oldfield2}}
{$sort:{field1:1,field2:-1}}
{$limit},{$skip}
{$unwind:"$listfield"} 将数组中的元素分配到多行(拉平数组)
  • 筛选出选择分布式数据库原理与应用的学生信息
json 复制代码
var 步骤1 = {$match:{"courses.course":"分布式数据库原理与应用"}};
var 步骤1 = {$match:{"courses.course":/分布式/}};//正则表达式,匹配包含"分布式"
var 步骤数组 = [步骤1];
db.students.aggregate(步骤数组);
  • 统计男女生人数 0女生 1男生
js 复制代码
//select count(*) as 人数,gender from students group by gender
//group操作符,取值进行group by
var 步骤1 = {$group:{_id:"$gender",人数:{$sum:1}}};
var 步骤数组 = [步骤1];
db.students.aggregate(步骤数组);
  • 为了让刚才的结果更直观,用到project ,这个阶段在数据处理过程中起到了选择、重命名和计算字段的重要作用。
json 复制代码
var 步骤1 = {$group:{_id:"$gender",人数:{$sum:1}}};
var 步骤2 = {$project:{性别:"$_id",人数:1,_id:0}};//1表示返回原来的人数
var 步骤数组 = [步骤1,步骤2];
db.students.aggregate(步骤数组);
  • 统计大数据专业男女生人数
json 复制代码
var 步骤0={$match:{"major":"大数据"}};
var 步骤1={$group:{_id:"$gender",人数:{$sum:1}}}//$表示值,sum:1相当于是count
var 步骤2={$project:{性别:"$_id",人数:1,_id:0}}
var 步骤数组=[步骤0,步骤1,步骤2]
db.students.aggregate(步骤数组)
  • 统计2022级大数据专业1班男女生人数
json 复制代码
//非分组做法,分别统计
db.students.count({major:"大数据",grade:2022,class:1,gender:0});//求出女生人数
db.students.count({major:"大数据",grade:2022,class:1,gender:1});//求出男生人数
//分组做法
var 先找出本班所有学生的记录 ={$match:{major:"大数据",grade:2022,class:1}};
var 计算男女生的数量={$group:{_id:"$gender",人数:{$sum:1}}};//相当于是求了count
db.students.aggregate([先找出本班所有学生的记录,计算男女生的数量]);
  • 统计2022级大数据专业1班男女体重和
json 复制代码
//db.students.aggregate([{阶段1},{阶段2},{阶段3},...])
//db.students.aggregate([先找出本班所有学生的记录,然后分男女计算体重的和,整理结果]);
//统计2022级大数据专业1班男女体重和
//select sum(bodyweight) as 总体重, gender as 性别 
//from tbstudents 
//group by gender
//where major="大数据" and grade=2020 and class=1
var 先找出本班所有学生的记录 = {$match:{major:"大数据",grade:2022,class:1}};
var 然后分男女计算体重的和 = {$group:{_id:"$gender",总体重:{$sum:"$body.weight"}}};
var 整理结果 = {$project:{_id:0,"性别":"$_id",总体重:"$总体重","单位":"kg"}};
db.students.aggregate([先找出本班所有学生的记录,然后分男女计算体重的和,整理结果])
  • 加减乘除运算符号 a d d 、 add、 add、substract、 m u l t i p l y 、 multiply、 multiply、divide
json 复制代码
var 先找出本班所有学生的记录 = {$match:{major:"大数据",grade:2022,class:1}};
//var 然后分男女计算体重的和 ={$group:{_id:分组字段,聚合字段:{$统计操作:$值字段}};
var 然后分男女计算体重的和 = {$group:{_id:"$gender",总体重:{$sum:"$body.weight"}}};
//var 整理结果 = {$project:{_id:0,"性别":"$_id",总体重:"$总体重","单位":"kg"}};
//var 整理结果 = {$project:{_id:0,"性别":"$_id",总体重:{$add:["$总体重",1000]},"单位":"kg"}};//通过$add增加1000
//var 整理结果 = {$project:{_id:0,"性别":"$_id",总体重:{$subtract:["$总体重",2000]},"单位":"kg"}};//通过$add减少2000
var 整理结果 = {$project:{_id:0,"性别":"$_id",总体重:{$multiply:["$总体重",2]},"单位":"kg"}};//通过$add减少2000
//var 整理结果 = {$project:{_id:0,"性别":"$_id",总体重:{$divide:["$总体重",1000]},"单位":"t"}};//通过$divide将体重从kg转换为吨 
db.students.aggregate([先找出本班所有学生的记录,然后分男女计算体重的和,整理结果]);
  • 统计各科课程的平均分
json 复制代码
// "courses": [
//        {
//            "course": "结构化数据存储与应用",
//            "credit": 2,
//            "score": 67
//        }
//    ]

//var 分组统计 = {$group:{_id:分组字段,聚合字段:{$统计操作:$值字段}}}
var 分组统计 = {$group:{_id:"$courses.course",平均分:{$avg:"$courses.score"}}};
db.students.aggregate([分组统计]);//直接这样查询有问题,对于数组\数组字段,无法直接分组统计

二维------>一维(unwind) ;

{ u n w i n d : " unwind:" unwind:"listfield"} 将列表中的元素分配到多行(拉平数组)

正确写法

json 复制代码
//需要先将数组拉平,也就是说将数组中的值拆出来与其他字段连接
// {A,B:[1,2]} => {A,B:1} {A,B:2}
var 平摊数组 = {$unwind:"$courses"};
var 分组统计 = {$group:{_id:"$courses.course", 平均分:{$avg:"$courses.score"}}};
//db.students.aggregate([平摊数组]);//此时可以看出,数组已经被拉开了
db.students.aggregate([平摊数组,分组统计]);
  • 在上一步基础上,利用 s o r t 和 sort和 sort和limit返回前3结果
json 复制代码
var 平摊数组 = {$unwind:"$courses"};
var 分组统计 = {$group:{_id:"$courses.course", 平均分:{$avg:"$courses.score"}}};
var 排序 = {$sort:{平均分:-1}};
var 返回前3结果 = { $limit : 3 }
db.students.aggregate([平摊数组,分组统计,排序,返回前3结果]);
  • 在上一步基础上,统计平均分大于74.5分的课程
json 复制代码
//select avg(score) 平均分,course from tbstudents group by course having 平均分>=74.5
var 平摊数组 = {$unwind:"$courses"};
var 分组统计 = {$group:{_id:"$courses.course", 平均分:{$avg:"$courses.score"}}};
var 结果筛选 = {$match:{"平均分":{$gte:74.5}}}
db.students.aggregate([平摊数组,分组统计,结果筛选])// 方法用于在集合上执行一系列的聚合操作。
  • 统计分布式数据库原理与应用的平均分
json 复制代码
var 平摊数组 = {$unwind:"$courses"};
var 分组统计 = {$group:{_id:"$courses.course", 平均分:{$avg:"$courses.score"}}};
var 结果筛选 = {$match:{"_id":/分布式/}}//非courses.course中,$match 是一个筛选操作符,用于过滤文档
//使用了正则表达式来匹配 _id 字段包含"分布式"字符串的文档。
var 整理结果 = {$project:{"course":"$_id","avgscore":{$round:["$平均分",2]},_id:0}}//$project 用于选择和重命名文档中的字段。指定将 _id 字段重命名为 course,平均分 字段重命名为 avgscore,并且排除 _id 字段在输出结果中显示(_id: 0 表示不显示 _id 字段)。{$round:["$平均分",2]}四舍五入,保留两位小数
db.students.aggregate([平摊数组,分组统计,结果筛选,整理结果])
  • 统计分布式数据库课程的平均分,要求保留两位小数
json 复制代码
//统计分布式数据库课程的平均分,要求保留两位小数
var 平摊数组 = {$unwind:"$courses"};
var 分组统计 = {$group:{_id:"$courses.course", 平均分:{$avg:"$courses.score"}}};
var 整理结果 = {$project:{"course":"$_id","avgscore":{$round:["$平均分",2]},_id:0}}//$project 用于选择和重命名文档中的字段。指定将 _id 字段重命名为 course,平均分 字段重命名为 avgscore,并且排除 _id 字段在输出结果中显示(_id: 0 表示不显示 _id 字段)。{$round:["$平均分",2]}四舍五入,保留两位小数
db.students.aggregate([平摊数组,分组统计,结果筛选,整理结果])
  • 统计各班级(专业\年级\班级)分布式数据库课程的平均分
json 复制代码
//方法一:直接连接
var 拉平数组 = {$unwind:"$courses"};
var 查找课程 = {$match:{"courses.course":/分布式/}};
//_id是一个组合字段,包括专业、年级、班级信息
var 按班级统计平均分 = {$group:{_id:{专业:"$major",年级:"$grade",班级:"$class"},平均分:{$avg:"$courses.score"}}}
var 整理结果 = {$project:{专业:"$_id.专业",年级:"$_id.年级",班级:"$_id.班级",平均分:{$round:["$平均分",2]},_id:0}};
db.students.aggregate([拉平数组,查找课程,按班级统计平均分,整理结果]);

//方法二:利用$concat连接,$tostring强制转换
var 拉平数组 = {$unwind:"$courses"};
var 查找课程 = {$match:{"courses.course":/分布式/}};
//_id是一个组合字段,包括专业、年级、班级信息
var 按班级统计平均分 = {$group:{_id:{"行政班级":{$concat:["$major",{$toString:"$grade"},"-0",{$toString:"$class"}]}},平均分:{$avg:"$courses.score"}}};
var 整理结果 = {$project:{"行政班级":"$_id.行政班级",平均分:{$round:["$平均分",2]},_id:0}};
var 排序 = {$sort:{"行政班级":1}};//按照行政班级升序
db.students.aggregate([拉平数组,查找课程,按班级统计平均分,整理结果,排序]);
  • 按专业求女生平均身高低于170的学生,并排序($sort)
json 复制代码
/* 
SQL: select AVG(height) as avgHeight, major as _id 
     from students 
	 where gender=0
	 group by major
	 having avgHeight<=170
	 sorted by avgHeight DESC
*/	
db.getCollection("students").aggregate([
 //第一步,查数据
 {$match:{gender:0}}
 //第二步,限制返回字段
 ,{$project:{_id:0,major:1, grade:1, class:1, height:"$body.height"}}
 //第三步,分组求平均值
 // _id: group by的字段, 字段名要加$符号前缀,表示是一个字段名
 // avgHeight: 新生成的平均值字段名
 // $avg: 平均值操作符,它的值为要求平均值的字段名,注意加$前缀
 ,{$group:{_id:"$major", avgHeight:{$avg:"$height"}}}
 //第四步,筛选聚合结果
 ,{$match:{avgHeight:{$lte:170}}}
 //第五步,排序,按照avgHeight的值从大到小排序, -1: DESC, 1:ASC
 ,{$sort:{avgHeight:-1}}
 //,{$limit:1}  //取结果中最接近170的值
])
  • 课堂练习

    1.统计各课程的平均分,并返回倒数第一名的结果
    2.统计本专业分布式数据库课程的平均分,并且保留两位小数

相关推荐
朴拙数科15 分钟前
MongoDB Atlas与MongoDB连接MCP服务器的区别解析
服务器·数据库·mongodb
辰哥单片机设计1 小时前
PH传感器详解(STM32)
数据库·mongodb
AscendKing6 小时前
mongo客户端操作mongodb记录
数据库·mongodb
辰哥单片机设计12 小时前
PTC加热片详解(STM32)
数据库·mongodb
快乐点吧13 小时前
【MongoDB】windows安装、配置、启动
数据库·windows·mongodb
yangmf204013 小时前
私有知识库 Coco AI 实战(二):摄入 MongoDB 数据
数据库·人工智能·mongodb·coco ai
键盘飞行员13 小时前
使用 Node、Express 和 MongoDB 构建一个项目工程
数据库·mongodb·express
zru_960213 小时前
MongoDB 入门使用教程
数据库·mongodb
wowocpp14 小时前
MongoDB Ubuntu 安装
数据库·mongodb
百万蹄蹄向前冲16 小时前
动图MangoDB 8.0.8从安装到使用
数据库·mongodb·豆包marscode