二十三、mongodb聚合操作
1、mongodb的聚合是什麼
聚合(aggregate)是基於資料處理的聚合管道,每個文件通過一個由多個階段(stage)組成的管道,可以對每個階段的管道進行分組、過濾等功能,然後經過一系列的處理,輸出相應的結果。
db.集合名稱.aggregate({管道:{表示式}})
db.xiaoshuo.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: match:{'age':{lt:40}}},{KaTeX parse error: Expected '}', got 'EOF' at end of input: group:{_id:'
gender’,counter:{$sum:1}}}])
2、mongodb的常用管道和表示式
2.1 常用管道命令
在mongodb中,⽂檔處理完畢後, 通過管道進⾏下⼀次處理 常用管道命令如下:
管道命令 | 含義 |
---|---|
$group | 將集合中的⽂檔分組, 可⽤於統計結果 |
$match | 過濾資料, 只輸出符合條件的⽂檔 |
$project | 修改輸⼊⽂檔的結構, 如重新命名、 增加、 刪除欄位、 建立計算結果 |
$sort | 將輸⼊⽂檔排序後輸出 |
$limit | 限制聚合管道返回的⽂檔數 |
$skip | 跳過指定數量的⽂檔, 並返回餘下的⽂檔 |
2.2 常用表示式
表示式:處理輸⼊⽂檔並輸出 語法:表示式:’$列名’
管道命令 | 含義 |
---|---|
$sum | 計算總和, $sum:1 表示以⼀倍計數 |
$avg | 計算平均值 |
$min | 獲取最⼩值 |
$max | 獲取最⼤值 |
$push | 在結果⽂檔中插⼊值到⼀個數組中 |
3、管道命令之$group
3.1 按照某個欄位進行分組
$group是所有聚合命令中用的最多的一個命令,用來將集合中的文件分組,可用於統計結果。
使用示例如下
db.stu.aggregate(
{$group:
{
_id:"$gender",
counter:{$sum:1}
}
}
)
其中注意點:
db.db_name.aggregate是語法,所有的管道命令都需要寫在其中
_id 表示分組的依據,按照哪個欄位進行分組,需要使用$gender表示選擇這個欄位進行分組
$sum:1 表示把每條資料作為1進行統計,統計的是該分組下面資料的條數
3.2 group by null
當我們需要統計整個文件的時候,$group 的另一種用途就是把整個文件分為一組進行統計
使用例項如下:
db.stu.aggregate(
{$group:
{
_id:null,
counter:{$sum:1}
}
}
)
其中注意點:
_id:null 表示不指定分組的欄位,即統計整個文件,此時獲取的counter表示整個文件的個數
3.3 資料透視
正常情況在統計的不同性別的資料的時候,需要知道所有的name,需要逐條觀察,如果通過某種方式把所有的name放到一起,那麼此時就可以理解為資料透視
使用示例如下:
- 統計不同性別的學生
db.stu.aggregate(
{$group:
{
_id:null,
name:{$push:"$name"}
}
}
)
- 使用$$ROOT可以將整個文件放入陣列中
db.stu.aggregate(
{$group:
{
_id:null,
name:{$push:"$$ROOT"}
}
}
)
3.4 動手
統計出每個hometown/age下的name的數量(同一個name只統計一次)
參考答案
db.stu.aggregate(
{$group:{_id:{hometown:'$hometown',age:'$age',name:'$name'}}},
{$group:{_id:{hometown:'$_id.hometown',age:'$_id.age'},count:{$sum:1}}})
分析:
- 第一個管道的作用:排除了同一個地區和年齡,有相同名字的人
- 第二個管道的作用:根據上一個分組,在進行分組資料統計
4、管道命令之$match
$match用於進行資料的過濾,是在能夠在聚合操作中使用的命令,和find區別在於$match 操作可以把結果交給下一個管道處理,而find不行。
使用示例如下:
- 查詢年齡大於20的學生
db.stu.aggregate(
{$match:{age:{$gt:20}}
)
- 查詢年齡大於20的男女學生的人數
db.stu.aggregate(
{$match:{age:{$gt:20}}},
{$group:{_id:"$gender",counter:{$sum:1}}}
)
5、管道命令之$project
$project用於修改文件的輸入輸出結構,例如重新命名,增加,刪除欄位
使用示例如下:
- 查詢學生的年齡、姓名,僅輸出年齡姓名
db.stu.aggregate(
{$project:{_id:0,name:1,age:1}}
)
- 查詢男女生人生,輸出人數
db.stu.aggregate(
{$group:{_id:"$gender",counter:{$sum:1}}}
{$project:{_id:0,counter:1}}
)
6、管道命令之$sort
$sort用於將輸入的文件排序後輸出
使用示例如下:
- 查詢學生資訊,按照年齡升序
db.stu.aggregate({$sort:{age:1}})
- 查詢男女人數,按照人數降序
db.stu.aggregate(
{$group:{_id:"$gender",counter:{$sum:1}}},
{$sort:{counter:-1}}
)
7、管道命令之$skip 和 $limit
$limit限制返回資料的條數
$skip 跳過指定的文件數,並返回剩下的文件數
同時使用時先使用skip在使用limit
使用示例如下:
- 查詢2條學生資訊
db.stu.aggregate(
{$limit:2}
)
- 查詢從第四條開始的學生資訊
db.stu.aggregate(
{$skip:3}
)
- 統計男女生人數,按照人數升序,返回第二條資料
db.stu.aggregate(
{$group:{_id:'$gender', count:{$sum:1}}},
{$sort:{count:1}},
{$skip:1},
{$limit:1}
)