在上一篇文章中咱們瞭解到了mongodb的基本操做,這一章咱們更進一步繼續來探討mongodb,廢話很少說,直接入正題吧。前端
mongodb中聚合(aggregate)主要用於處理數據(諸如統計平均值,求和等),並返回計算後的數據結果。有點相似sql語句中的count(*).java
例如如今有個需求,有一個保存這文章的集合,你可能但願找出發表文章最多的那個做者,假設每篇文章被保存爲mongodb中的一個文檔,這個需求咱們怎麼去實現呢?下面咱們就一步一步的來實現這個需求。node
db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)python
假設集合中的數據以下:mysql
{ "_id" : ObjectId("5a338a31ae83f6d96d3ef220"), "title" : "mongodb", "author" : "ck" }
{ "_id" : ObjectId("5a338a38ae83f6d96d3ef221"), "title" : "java", "author" : "ck" }
{ "_id" : ObjectId("5a338a4dae83f6d96d3ef222"), "title" : "node", "author" : "st" }
複製代碼
首先咱們先計算出每一個做者縮寫的文章數並排序,使用aggregate()計算結果以下所示:git
> db.col.aggregate([{ $group: { _id: "$author", num: { $sum : 1 } } },{ $sort : { "_id":1 } }])
{ "_id" : "ck", "num" : 2 }
{ "_id" : "st", "num" : 1 }
複製代碼
直接一步到位的以下所示:github
> db.col.aggregate([{ $group: { _id: "$author", num: { $sum : 1 } } },{ $sort : { "_id":1 } }, { $limit:1 }])
{ "_id" : "ck", "num" : 2 }
複製代碼
下表展現了一些聚合的表達式:算法
表達式 | 描述 | 實例 |
---|---|---|
$sum | 計算總和 | db.mycol.aggregate([{![]() ![]() |
$avg | 計算平均值 | db.mycol.aggregate([{![]() ![]() |
$min | 獲取集合中全部文檔對應值得最小值。 | db.mycol.aggregate([{![]() ![]() |
$max | 獲取集合中全部文檔對應值得最大值 | db.mycol.aggregate([{![]() ![]() |
$push | 在結果文檔中插入值到一個數組中。 | db.mycol.aggregate([{![]() ![]() |
$addToSet | 在結果文檔中插入值到一個數組中,但不建立副本。 | db.mycol.aggregate([{![]() ![]() |
$first | 根據資源文檔的排序獲取第一個文檔數據。 | db.mycol.aggregate([{![]() ![]() |
$last | 根據資源文檔的排序獲取最後一個文檔數據 | db.mycol.aggregate([{![]() ![]() |
管道在Unix和Linux中通常用於將當前命令的輸出結果做爲下一個命令的參數。 MongoDB的聚合管道將MongoDB文檔在一個管道處理完畢後將結果傳遞給下一個管道處理。管道操做是能夠重複的。 表達式:處理輸入文檔並輸出。表達式是無狀態的,只能用於計算當前聚合管道的文檔,不能處理其它的文檔。 這裏咱們介紹一下聚合框架中經常使用的幾個操做:sql
$project:修改輸入文檔的結構。能夠用來重命名、增長或刪除域,也能夠用於建立計算結果以及嵌套文檔。mongodb
match使用MongoDB的標準查詢操做。
$limit:用來限制MongoDB聚合管道返回的文檔數。
$skip:在聚合管道中跳過指定數量的文檔,並返回餘下的文檔。
$unwind:將文檔中的某一個數組類型字段拆分紅多條,每條包含數組中的一個值。
$group:將集合中的文檔分組,可用於統計結果。
$sort:將輸入文檔排序後輸出。
$geoNear:輸出接近某一地理位置的有序文檔。
一、$project實例
db.article.aggregate(
{ $project : {
title : 1 ,
author : 1 ,
}}
);
複製代碼
這樣的話結果中就只還有_id,tilte和author三個字段了,默認狀況下_id字段是被包含的,若是要想不包含_id話能夠這樣:
db.article.aggregate(
{ $project : {
_id : 0 ,
title : 1 ,
author : 1
}});
複製代碼
2.$match實例
db.articles.aggregate( [
{ $match : { score : { $gt : 70, $lte : 90 } } },
{ $group: { _id: null, count: { $sum: 1 } } }
] );
複製代碼
group管道操做符進行處理。
3.$skip實例
db.article.aggregate(
{ $skip : 5 });
複製代碼
通過$skip管道操做符處理後,前五個文檔被"過濾"掉。
目前咱們一直使用的是單臺服務器,一個mongod服務器進程。若是隻是用做學習和開發,這是能夠的,可是若是用到生產環境中,風險會很高。若是服務器崩潰了或者不可訪問了怎麼辦?數據庫至少會有一段時間不可用。若是是硬件除了問題,可能須要將數據轉移到另外一個機器上。在最壞的狀況下,磁盤或者網絡問題可能會致使數據損壞或者數據不可訪問。
使用複製能夠將數據副本保存到多臺服務器上,建議在全部的生產環境中都要使用。使用mongodb的複製功能,即便一臺或多臺服務器出錯,也能夠保證應用程序正常運行和數據安全。
保障數據的安全性
數據高可用性
災難恢復
無需停機維護(如備份, 重建索引, 壓縮)
分佈式讀取數據
1.數據的一致性:主節點是惟一的,沒有mysql那樣的雙主結構,若是當前主節點出現故障後,集羣會自動容災,經過選舉,來選舉出來一個合適的從節點來充當新的主節點,因此主節點是惟一的,但不是固定的。
2.大多數原則:集羣存貨節點小於等於二分之一時集羣則不可寫,只可讀。若是複製集的服務器掛了通常就無法選舉了,將所有將爲從節點。
3.從庫沒法寫入:只有主節點可寫入數據,從節點只可讀。
關於複製集以及下面的分片這一塊,想深刻研究的同窗能夠自行學習,原諒我只是個前端,哈哈。。
分片是指將數據拆分,將其分散存放在不一樣的機器上的過程。有時也用分區來表示這個概念。將數據分散到不一樣的機器上,不須要功能強大的大型計算機就能夠存儲更多的數據,處理更大的負載。
幾乎全部數據庫軟件都能進行手動分片。應用須要維護與若干不一樣數據服務器的連接,每一個連接仍是徹底獨立的。應用程序管理不一樣服務器上不一樣數據的存儲,還管理在合適的數據上查詢數據的工做。這種方法能夠很好的工做,可是很是難以維護,好比向集羣添加節點或從集羣刪除節點都很款南,調整數據分佈和負載模式也不輕鬆。
mongodb支持自動分片,可使數據庫架構對應用程序不可見,也能夠簡化系統管理。對應用程序而言,好像始終在使用一個單機的mongodb服務器同樣。另外一方面,mongodb自動處理數據在分片上的分部,也更容易添加和刪除分片。
無論從開發角度仍是運營角度來講,分片都是最困難最複雜的mongodb配置方式。
mongodb的分片機制容許你建立一個包含許多臺機器(分片)的集羣,將數據子集分散在集羣中,每一個分片維護者一個數據集合的子集。與單機服務器和副本集相比,使用集羣架構可使應用程序具備更大的數據處理能力。
這裏有一點要注意,許多人可能會混淆複製和分片的概念。記住,複製是讓多臺服務器都擁有一樣的數據副本,每一臺服務器都是其餘服務器的鏡像,而每個分片都有其餘分片擁有不一樣的數據子集。
分片的目標之一是建立一個擁有5臺、10臺甚至1000臺機器的集羣,整個集羣對應用程序來講就像是一臺單機服務器。爲了對應用程序隱藏數據庫架構的細節,在分片以前要先執行mongos進行一次路由過程。這個路由服務器維護着一個「內容列表」,指明瞭每一個分片包含什麼數據內容。應用程序只須要鏈接到路由服務器,就能夠像使用單機服務器同樣進行正常的請求了,以下圖所示。路由服務器知道哪些數據位於哪一個分片,能夠將請求轉發給相應的分片。每一個分片對請求的相應都會發送給路由服務器,路由服務器將全部相應合併在一塊兒,返回給應用程序。對應用程序來講,它只知道本身是鏈接到了一臺單機mongod服務器,以下圖所示:
衆所周知,數據安全很是重要,那麼咱們應該怎麼對咱們的mongodb進行安全加固呢?
修改默認的mongodb端口(默認爲:27017)爲其餘端口。
1.經過安全組防火牆或服務器操做系統配置的防火牆對訪問源IP進行控制,若是僅對內網服務器提供服務,建議禁止將mongodb服務發佈到互聯網上。
該選項能夠限制監聽接口IP,當在啓動mongodb的時候,使用 --bind_ip 192.168.0.1 表示啓動IP地址綁定,數據庫實例將只監聽192.168.0.1的請求。
在admin數據庫中建立用戶,如用戶名supper,密碼supWDxsf67%H(此處爲舉例說明,請勿使用此帳號密碼)。
1.在未開啓認證的環境下,登陸到數據庫。
> [mongodb@rac3 bin]$ ./mongo 127.0.0.1:27028 (此處修改了默認端口)
MongoDB shell version: 2.0.1
connecting to: 127.0.0.1:27028/test
複製代碼
2.切換到admin數據庫
> use admin
switched to db admin
複製代碼
3.建立管理員帳號
> db.addUser("supper", "supWDxsf67%H")或
> db.createUser({user:"supper",pwd:"supWDxsf67%H",roles:["root"]})
{ "n" : 0, "connectionId" : 4, "err" : null, "ok" : 1 }
{
"user" : "supper",
"readOnly" : false,
"pwd" : "51a481f72b8b8218df9fee50b3737c44",
"_id" : ObjectId("4f2bc0d357a309043c6947a4")
}
複製代碼
管理員帳號將在system.users中。
> db.getCollectionNames()
[ "system.indexes", "system.users", "system.version" ]
複製代碼
說明:
mongodb從v3版本開始取消使用addUser方法,採用db.createUser方法建立用戶;
帳號不要設置爲常見帳號,密碼須要知足必定的複雜度,長度至少八位以上,幷包括大小寫字母、數字、特殊字符混合體,不要使用生日、姓名、身份證編號等常見密碼。
4.驗證用戶是否建立成功。
> db.auth("supper","supWDxsf67%H")
> exit "system.version" ]
bye
複製代碼
5.結束進程,重啓MongoDB服務。
> ./mongod --dbpath=/path/mongodb --bind_ip=192.168.0.1 --port=27028 --fork=true logpath=/path/mongod.log &
複製代碼
說明:
MongoDB自身帶有一個HTTP服務和並支持REST接口(在V2.6之後這些接口默認是關閉的)。MongoDB默認使用默認端口監聽Web服務,通常不須要經過Web方式進行遠程管理,建議禁用。 修改配置文件或在啓動的時候選擇–nohttpinterface參數便可。
nohttpinterface = false
複製代碼
審計功能能夠用來記錄用戶對數據庫的全部相關操做。這些記錄可讓系統管理員在須要的時候分析數據庫在什麼時段發生了什麼事情。
MongoDB集羣之間以及從客戶端鏈接到MongoDB實例的鏈接應該使用SSL。使用SSL對性能沒有影響而且能夠防範相似於man-in-the-middle的攻擊。
注意MongoDB社區版默認並不支持SSL。您能夠選用MongoDB企業版(支持SSL),或者從源碼從新編譯MongoDB並使用—ssl選項來得到SSL功能。
以上全部配置,推薦以配置文件形式保存配置。
[mongodb@rac3 bin]$ vim /path/mongod.conf
port=27028-------端口。默認爲27017端口,MongoDB的默認服務TCP端口,監聽客戶端鏈接。要是端口設置小於1024,好比1021,則須要root權限啓動,不能用mongodb賬號啓動,(普通賬號即便是27017也起不來)不然報錯:[mongo --port=1021 鏈接]
bind_ip=192.168.0.1------綁定地址。默認127.0.0.1,只能經過本地鏈接。進程綁定和監聽來自這個地址上的應用鏈接。要是須要給其餘服務器鏈接,則須要註釋掉這個或則把IP改爲本機地址,如192.168.200.201[其餘服務器用 mongo --host=192.168.200.201 鏈接] ,能夠用一個逗號分隔的列表綁定多個IP地址。
logpath=/path/mongod.log------開啓日誌審計功能,此項爲日誌文件路徑,能夠自定義指定。
pidfilepath=/path/mongod.pid------進程ID,沒有指定則啓動時候就沒有PID文件。
auth=true------用戶認證,默認false。不須要認證。當設置爲true時候,進入數據庫須要auth驗證,當數據庫裏沒有用戶,則不須要驗證也能夠操做。直到建立了第一個用戶,以後操做都須要驗證。
logappend=true------寫日誌的模式:設置爲true爲追加。默認是覆蓋。若是未指定此設置,啓動時MongoDB的將覆蓋現有的日誌文件。
fork=true------是否後臺運行,設置爲true 啓動 進程在後臺運行的守護進程模式。默認false。
nohttpinterface = false------是否禁止http接口,即28017 端口開啓的服務。默認false,支持。
複製代碼
而後,啓動MongoDB服務時加載配置文件。
[mongodb@rac3 bin]$ ./mongod -f /path/mongod.conf
複製代碼
建議您梳理業務數據,對關鍵的敏感數據加密後入庫,例如:帳號、密碼、郵箱地址、手機號碼、身份ID等其餘數據。加密算法推薦選擇國際通用加密算法和屢次加鹽組合自定義算法,防止加密算法被破解。
即便黑客獲取數據後,也查看不了數據,經過「看不懂」的數據加密方式將損失降到最低。
完善的備份策略是保證數據安全的最後一根救命稻草。
推薦:可靠的本地備份+遠程備份存儲方案
本地備份
1.MongoDB備份方式
>mongodump -h dbhost -d dbname -o dbdirectory
-h:
MongDB所在服務器地址,例如:127.0.0.1,固然也能夠指定端口號:127.0.0.1:27017
-d:
須要備份的數據庫實例,例如:test
-o:
備份的數據存放位置,例如:c:\data\dump,該目錄須要提早創建,在備份完成後,系統自動在dump目錄下創建一個test目錄,這個目錄裏面存放該數據庫實例的備份數據。
複製代碼
2.MongoDB數據恢復
mongodb使用 mongorestore 命令來恢復備份的數據。
語法
mongorestore命令腳本語法以下:
>mongorestore -h dbhost -d dbname --directoryperdb dbdirectory
-h:
MongoDB所在服務器地址
-d:
須要恢復的數據庫實例,例如:test,這個名稱也能夠和備份時候的不同,好比test2。
--directoryperdb:
備份數據所在位置,例如:c:\data\dump\test。
--drop:
恢復的時候,先刪除當前數據,而後恢復備份的數據。就是說,恢復後,備份後添加修改的數據都會被刪除,慎用!
複製代碼
3.Mongodump命令可選參數列表以下所示。
語法 | 描述 | 實例 |
---|---|---|
mongodump --host HOST_NAME --port PORT_NUMBER | 該命令將備份全部mongodb數據 | mongodump --host w3cschool.cc --port 27017 |
mongodump --dbpath DB_PATH --out BACKUP_DIRECTORY | mongodump --dbpath /data/db/ --out /data/backup | |
mongodump --collection COLLECTION --db DB_NAME | 該命令將備份指定數據庫的集合 | mongodump --collection mycol --db test |
4.備份策略
全量備份:能夠最快的時間快速恢復全部數據,缺點是備份成本大,時間長
全量備份+增量備份:能夠較快的恢復全部數據,缺點是恢復時間長,若是增量數據有問題,沒法恢復全部數據。
搭建從庫:直接切換到從庫,前提是從庫的數據安全可靠。