1. 程式人生 > >MongoDB知識樹整理【二 高階】

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