MongoDB知識樹整理【二 高階】
mongodb的高階操作,包括聚合、主從複製、分片、備份與恢復、MR
聚合 aggregate
- 聚合(aggregate)主要用於計算資料,類似sql中的sum()、avg()
- 語法
db.集合名稱.aggregate([{管道:{表示式}}])
管道
- 管道在Unix和Linux中一般用於將當前命令的輸出結果作為下一個命令的輸入
ps ajx | grep mongo
- 在mongodb中,管道具有同樣的作用,文件處理完畢後,通過管道進行下一次處理
- 常用管道
- $group:將集合中的文件分組,可用於統計結果
- $match:過濾資料,只輸出符合條件的文件
- $project:修改輸入文件的結構,如重新命名、增加、刪除欄位、建立計算結果
- $sort:將輸入文件排序後輸出
- $limit:限制聚合管道返回的文件數
- $skip:跳過指定數量的文件,並返回餘下的文件
- $unwind:將陣列型別的欄位進行拆分
表示式
- 處理輸入文件並輸出
- 語法
表示式:'$列名'
- 常用表示式
- $sum:計算總和,$sum:1同count表示計數
- $avg:計算平均值
- $min:獲取最小值
- $max:獲取最大值
- $push:在結果文件中插入值到一個數組中
- $first:根據資源文件的排序獲取第一個文件資料
- $last:根據資源文件的排序獲取最後一個文件資料
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
$group
- 將集合中的文件分組,可用於統計結果
- _id表示分組的依據,使用某個欄位的格式為'$欄位'
- 例1:統計男生、女生的總人數
db.stu.aggregate([
{$group:
{
_id:'$gender',
counter:{$sum:1}
}
}
])
Group by null
- 將集合中所有文件分為一組
- 例2:求學生總人數、平均年齡
db.stu.aggregate([
{$group:
{
_id:null,
counter:{$sum:1},
avgAge:{$avg:'$age'}
}
}
])
透視資料
- 例3:統計學生性別及學生姓名
db.stu.aggregate([
{$group:
{
_id:'$gender',
name:{$push:'$name'}
}
}
])
- 使用$$ROOT可以將文件內容加入到結果集的陣列中,程式碼如下
db.stu.aggregate([
{$group:
{
_id:'$gender',
name:{$push:'$$ROOT'}
}
}
])
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
索引
- 和mysql中的索引概念相同,索引也是為了查詢速度的提升
- mongodb也支援索引,以提升查詢速度
mongodb的客戶端shell同樣也是一個js編譯器,所以可以通過寫js程式碼來實現mongodb的一些相關操作,比如插入資料
for(i=0;i<100000;i++){
db.t1.insert({name:'test'+1,age:i})
}
查詢資料時的效能測試:
- 查詢資料 db.t1.find({name:'test10000'})
- 使用explain()命令進行查詢效能分析 db.t1.find({name:'test10000'}).explain('executionStats')
其中的executionStats下的executionTimeMillis表示整體查詢時間,單位是毫秒
效能分析結果如下圖【其中的96表示使用的時間為96毫秒】
- 建立索引的語法:
#建立索引
#1表示升序,-1表示降序
db.集合.ensureIndex({屬性:1})
如:對name屬性建立索引
db.t1.ensureIndex({name:1})
- 對索引屬性查詢
執行同樣的查詢,並進行查詢效能分析
db.t1.find({name:'test10000'}).explain('executionStats')
基於那個屬性查詢,就基於那個屬性建立索引
- 索引的命令
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
超級管理員
- 為了更安全的訪問mongodb,需要訪問者提供使用者名稱和密碼,於是需要在mongodb中建立使用者
- 採用了角色-使用者-資料庫的安全管理方式
- 常用系統角色如下:
- root:只在admin資料庫中可用,超級賬號,超級許可權
- Read:允許使用者讀取指定資料庫
- readWrite:允許使用者讀寫指定資料庫
- 建立超級管理使用者
use admin
db.createUser({
user:'admin',
pwd:'123',
roles:[{role:'root',db:'admin'}]
})
啟用安全認證
- 修改配置檔案
sudo vi /etc/mongod.conf
- 啟用身份驗證
- 注意:keys and values之間一定要加空格, 否則解析會報錯
security:
authorization: enabled
- 重啟服務
sudo service mongod stop
sudo service mongod start
- 終端連線
mongo -u 'admin' -p '123' --authenticationDatabase 'admin'
普通使用者管理
- 使用超級管理員登入,然後進入使用者管理操作
- 檢視當前資料庫的使用者
use test1
show users
- 建立普通使用者
db.createUser({
user:'t1',
pwd:'123',
roles:[{role:'readWrite',db:'test1'}]
})
- 終端連線
mongo -u t1 -p 123 --authenticationDatabase test1
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
複製(副本集)
什麼是複製
- 複製提供了資料的冗餘備份,並在多個伺服器上儲存資料副本,提高了資料的可用性,並可以保證資料的安全性
- 複製還允許從硬體故障和服務中斷中恢復資料
為什麼要複製
- 資料備份
- 資料災難恢復
- 讀寫分離
- 高(24* 7)資料可用性
- 無宕機維護
- 副本集對應用程式是透明
複製的工作原理
- 複製至少需要兩個節點A、B...
- A是主節點,負責處理客戶端請求
- 其餘的都是從節點,負責複製主節點上的資料
- 節點常見的搭配方式為:一主一從、一主多從
- 主節點記錄在其上的所有操作,從節點定期輪詢主節點獲取這些操作,然後對自己的資料副本執行這些操作,從而保證從節點的資料與主節點一致
- 主節點與從節點進行資料互動保障資料的一致性
複製的特點
- N 個節點的叢集
- 任何節點可作為主節點
- 所有寫入操作都在主節點上
- 自動故障轉移
- 自動恢復
設定複製節點
- 接下來的操作需要開啟多個終端視窗,而且可能會連線多臺ubuntu主機,會顯得有些亂,建議在xshell中實現
- step1:建立資料庫目錄t1、t2
- 在Desktop目錄下演示,其它目錄也可以,注意許可權即可
mkdir t1
mkdir t2
- step2:使用如下格式啟動mongod,注意replSet的名稱是一致的
mongod --bind_ip 192.168.196.128 --port 27017 --dbpath ~/Desktop/t1 --replSet rs0
mongod --bind_ip 192.168.196.128 --port 27018 --dbpath ~/Desktop/t2 --replSet rs0
- step3:連線主伺服器,此處設定192.168.196.128:27017為主伺服器
mongo --host 192.168.196.128 --port 27017
- step4:初始化
rs.initiate()
- 初始化完成後,提示符如下圖:
- step5:檢視當前狀態
rs.status()
- 當前狀態如下圖:
- step6:新增複本集
rs.add('192.168.196.128:27018')
- step7:複本集新增成功後,當前狀態如下圖:
- step8:連線第二個mongo服務
mongo --host 192.168.196.128 --port 27018
- 連線成功後,提示符如下圖:
- step9:向主伺服器中插入資料
use test1
for(i=0;i<10;i++){db.t1.insert({_id:i})}
db.t1.find()
- step10:在從伺服器中插查詢
- 說明:如果在從伺服器上進行讀操作,需要設定rs.slaveOk()
rs.slaveOk()
db.t1.find()
其它說明
- 刪除從節點
rs.remove('192.168.196.128:27018')
- 關閉主伺服器後,再重新啟動,會發現原來的從伺服器變為了從伺服器,新啟動的伺服器(原來的從伺服器)變為了從伺服器
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
備份
- 語法
mongodump -h dbhost -d dbname -o dbdirectory
- -h:伺服器地址,也可以指定埠號
- -d:需要備份的資料庫名稱
- -o:備份的資料存放位置,此目錄中存放著備份出來的資料
- 例1
sudo mkdir test1bak
sudo mongodump -h 192.168.196.128:27017 -d test1 -o ~/Desktop/test1bak
資料存在bson裡面,結構存在json裡面了
恢復
- 語法
mongorestore -h dbhost -d dbname --dir dbdirectory
- -h:伺服器地址
- -d:需要恢復的資料庫例項
- --dir:備份資料所在位置
- 例2
mongorestore -h 192.168.196.128:27017 -d test2 --dir ~/Desktop/test1bak/test1
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
分片
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
MapReduce