根據你對軟體的要求,你可能優先考慮靈活性、可擴充套件性、效能或速度。因此,開發者和企業在為他們的需求挑選資料庫時常常感到困惑。如果你需要一個能提供高靈活性和可擴充套件性的資料庫,以及用於客戶分析的資料聚合,那麼MongoDB可能是你的最佳選擇!
在這篇文章中,我們將討論MongoDB資料庫的結構以及如何建立、監控和管理你的資料庫!
MongoDB資料庫是如何結構化的?
MongoDB是一個無模式的NoSQL資料庫。這意味著你不像SQL資料庫那樣為表/資料庫指定一個結構。
你知道嗎,NoSQL資料庫實際上比關係型資料庫更快?這是由於索引、分片和聚合管道等特性。MongoDB也因其快速的查詢執行而聞名。這就是為什麼它被谷歌、豐田和福布斯等公司所青睞。
下面,我們將探討MongoDB的一些關鍵特徵。
文件
MongoDB有一個文件資料模型,將資料儲存為JSON文件。文件自然地對映到應用程式程式碼中的物件,使開發人員更直接地使用它。
在關係型資料庫表中,你必須新增一個列才能新增一個新欄位。而JSON文件中的欄位則不是這樣的。JSON文件中的欄位可以因文件而異,所以它們不會被新增到資料庫的每一條記錄中。
文件可以儲存像陣列這樣的結構,可以巢狀來表達層次關係。此外,MongoDB將文件轉換為二進位制JSON(BSON)型別。這確保了更快的訪問速度,並增加了對各種資料型別的支援,如字串、整數、布林型數字等等
複製集
當你在MongoDB中建立一個新的資料庫時,系統會自動為你的資料再建立至少兩個副本。這些副本被稱為 “複製集”,它們之間不斷複製資料,確保提高你的資料的可用性。它們還提供保護,防止在系統故障或計劃維護期間出現停機。
集合
一個集合是一組與一個資料庫相關的檔案。它們類似於關係型資料庫中的表。
然而,集合要靈活得多。首先,它們不依賴於一個模式。其次,這些檔案不需要是相同的資料型別。
要檢視屬於一個資料庫的集合的列表,請使用listCollections
命令。
聚合管道
你可以使用這個框架來會幾個運算子和表示式。它很靈活,因為它允許你處理、轉換和分析任何結構的資料。
正因為如此,MongoDB允許快速的資料流和跨越150個運算子和表示式的功能。它也有幾個階段,比如聯合階段,可以靈活地將多個集合的結果放在一起。
索引
你可以對MongoDB文件中的任何欄位進行索引,以提高其效率並改善查詢速度。索引通過掃描索引來限制所檢查的文件,從而節省時間。這不比讀取集合中的每一個文件要好得多嗎?
你可以使用各種索引策略,包括多個欄位的複合索引。例如,假設你有幾個文件在不同的欄位中包含了僱員的名字和姓氏。如果你希望返回姓和名,你可以建立一個包括 “姓 “和 “名 “的索引。這比在 “姓 “和 “名 “上建立一個索引要好得多。
你可以利用效能顧問等工具來進一步瞭解哪些查詢可以從索引中受益。
分片
分片將一個單一的資料集分佈在多個資料庫中。然後,該資料集可以儲存在多臺機器上,以增加系統的總儲存容量。這是因為它將較大的資料集分割成較小的塊,並將它們儲存在不同的資料節點中。
MongoDB在集合層面對資料進行分片,將集合中的文件分佈在叢集中的分片上。這確保了可擴充套件性,允許該架構處理最大的應用程式。
如何建立MongoDB資料庫
你需要首先安裝適合你的作業系統的MongoDB包。轉到 ‘Download MongoDB Community Server‘ 頁面。從可用的選項中,選擇最新的 “version”,”package”格式為zip檔案,”platform”為你的作業系統,然後點選 “Download”,如下圖所示。
MongoDB社羣伺服器的下載過程 (圖片來源:MongoDB Community Server)
這個過程非常簡單,所以你很快就能在你的系統中安裝MongoDB!
一旦你完成了安裝,開啟你的命令提示符,輸入 mongod -version
來驗證它。如果你沒有得到下面的輸出,而是看到一串錯誤,你可能要重新安裝它。
驗證MongoDB的版本 (圖片來源:configserverfirewall)
使用MongoDB Shell
在我們開始之前,請確保:
- 你的客戶端有傳輸層安全,並且在你的IP允許列表中。
- 你在所需的MongoDB叢集上有一個使用者賬戶和密碼。
- 你已經在你的裝置上安裝了MongoDB。
步驟1:訪問MongoDB外殼
要訪問MongoDB的外殼,請鍵入以下命令。
net start MongoDB
這應該會有以下輸出:
MongoDB伺服器初始化 (Image source: c-sharpcorner)
前面的命令初始化了MongoDB伺服器。要執行它,我們必須在命令提示符中鍵入 mongo
。
執行MongoDB伺服器 (Image source: bmc)
在MongoDB shell中,我們可以執行命令來建立資料庫、插入資料、編輯資料、釋出管理命令和刪除資料。
第2步:建立你的資料庫
與SQL不同,MongoDB沒有一個資料庫建立命令。相反,有一個叫做 use
的關鍵詞,它可以切換到一個指定的資料庫。如果該資料庫不存在,它將建立一個新的資料庫,否則,它將連結到現有資料庫。
例如,要啟動一個名為 “company”的資料庫,請鍵入
use Company
在MongoDB中建立資料庫
你可以鍵入 db
來確認你剛剛在系統中建立的資料庫。如果你建立的新資料庫彈出,說明你已經成功連線到它。
如果你想檢查現有的資料庫,輸入 show dbs
,它將返回你係統中的所有資料庫:
檢視MongoDB中的資料庫
預設情況下,安裝MongoDB會建立管理、配置和本地資料庫。
你是否注意到,我們建立的資料庫沒有顯示?這是因為我們還沒有將數值儲存到資料庫中!這就是我們的資料庫。我們將在資料庫管理部分討論插入的問題。
使用Atlas UI
你也可以開始使用MongoDB的資料庫服務Atlas。雖然你可能需要付費才能使用Atlas的某些功能,但大多數資料庫功能都可以通過免費層獲得。免費層的功能對於建立一個MongoDB資料庫來說是綽綽有餘的。
在我們開始之前,請確保:
- 你的IP是在允許列表中。
- 你在你想使用的MongoDB叢集上有一個使用者賬戶和密碼。
要用AtlasUI建立一個MongoDB資料庫,請開啟一個瀏覽器視窗並登入到https://cloud.mongodb.com。從你的叢集頁面,點選Browse Collections。如果叢集中沒有資料庫,你可以通過點選Add My Own Data按鈕建立你的資料庫。
提示將要求你提供一個資料庫和集合的名稱。一旦你命名了它們,點選Create,你就完成了! 現在你可以輸入新的檔案或使用驅動程式連線到資料庫。
如何管理MongoDB資料庫
在本節中,我們將介紹一些有效管理MongoDB資料庫的巧妙方法。你可以通過使用MongoDB指南針或通過集合來實現。
使用集合
雖然關係型資料庫擁有定義明確的表,有指定的資料型別和列,但NoSQL有集合而不是表。這些集合沒有任何結構,而且文件可以變化–你可以有不同的資料型別和欄位,而不需要在同一個集合中匹配另一個文件的格式。
為了演示,讓我們建立一個名為 “Employee “的集合,並向其中新增一個文件。
db.Employee.insert( { "Employeename" : "Chris", "EmployeeDepartment" : "Sales" } )
如果插入成功,它將返回 WriteResult({ "nInserted" : 1 })
:
在MongoDB中成功插入
這裡,”db “指的是當前連線的資料庫。”Employee “是在公司資料庫中新建立的集合。
我們沒有在這裡設定主鍵,因為MongoDB會自動建立一個名為”_id “的主鍵欄位,併為其設定一個預設值。
執行下面的命令來檢查JSON格式的集合。
db.Employee.find().forEach(printjson)
輸出:
{ "_id" : ObjectId("63151427a4dd187757d135b8"), "Employeename" : "Chris", "EmployeeDepartment" : "Sales" }
雖然”_id “值是自動分配的,但你可以改變預設主鍵的值。這一次,我們將在 “Employee”資料庫中插入另一個文件,”_id “值為 “1”。
db.Employee.insert( { "_id" : 1, "EmployeeName" : "Ava", "EmployeeDepartment" : "Public Relations" } )
在執行 db.Employee.find().forEach(printjson)
命令時,我們得到如下輸出:
集合中的檔案與它們的主鍵
在上面的輸出中,”Ava “的”_id “值被設定為 “1”,而不是被自動分配一個值。
現在我們已經成功地將數值新增到資料庫中,我們可以使用以下命令檢查它是否顯示在我們系統中的現有資料庫下:
show dbs
顯示資料庫的列表
然後就可以了! 你已經成功地在你的系統中建立了一個資料庫!
使用MongoDB Compass
儘管我們可以通過Mongo shell來處理MongoDB伺服器,但有時會很乏味。在生產環境中,你可能會遇到這種情況。
然而,有一個由MongoDB建立的Compass工具(適當地命名為Compass)可以使它更容易。它有一個更好的GUI,並增加了一些功能,如資料視覺化、效能分析,以及對資料、資料庫和集合的CRUD(建立、讀取、更新、刪除)訪問。
你可以為你的作業系統下載Compass IDE,並通過其簡單的過程安裝它。
接下來,開啟應用程式,通過貼上連線字串建立與伺服器的連線。如果你找不到它,你可以點選Fill in connection fields individually。如果你在安裝MongoDB時沒有改變埠號,只需點選連線按鈕,你就可以進去了 否則,只要輸入你設定的值,然後點選Connect。
MongoDB的新連線視窗 (圖片來源: mongodb)
接下來,在新連線視窗中提供主機名、埠和認證。
在MongoDB Compass中,你可以同時建立一個資料庫並新增其第一個集合。下面是你如何做的。
- 點選Create Database,開啟提示。
- 輸入資料庫的名稱和它的第一個集合。
- 點選Create Database。
你可以通過點選你的資料庫名稱在資料庫中插入更多的檔案,然後點選集合的名稱,看到Documents標籤。然後,你可以點選Add Data按鈕,將一個或多個文件插入你的集合中。
在新增你的文件時,你可以一次輸入一個,也可以在一個陣列中輸入多個文件。如果你要新增多個文件,請確保這些以逗號分隔的文件被括在方括號中。比如說:
{ _id: 1, item: { name: "apple", code: "123" }, qty: 15, tags: [ "A", "B", "C" ] }, { _id: 2, item: { name: "banana", code: "123" }, qty: 20, tags: [ "B" ] }, { _id: 3, item: { name: "spinach", code: "456" }, qty: 25, tags: [ "A", "B" ] }, { _id: 4, item: { name: "lentils", code: "456" }, qty: 30, tags: [ "B", "A" ] }, { _id: 5, item: { name: "pears", code: "000" }, qty: 20, tags: [ [ "A", "B" ], "C" ] }, { _id: 6, item: { name: "strawberry", code: "123" }, tags: [ "B" ] }
最後,單擊 “Insert“,將檔案新增到你的集合中。這就是一個檔案的正文的樣子:
{ "StudentID" : 1 "StudentName" : "JohnDoe" }
這裡,欄位名是 “StudentID “和 “StudentName”。欄位值分別為 “1 “和 “JohnDoe”。
有用的命令
你可以通過角色管理和使用者管理命令來管理這些集合。
使用者管理命令
MongoDB使用者管理命令包含與使用者有關的命令。我們可以使用這些命令建立、更新和刪除使用者。
(1)DropUser
該命令從指定的資料庫中刪除一個使用者。下面是其語法。
db.dropUser(username, writeConcern)
這裡,username
是一個必填欄位,它包含了使用者的認證和訪問資訊的檔案。可選的欄位 writeConcern
包含了對建立操作的寫關注程度。寫入關注的級別可以由可選欄位 writeConcern
決定。
在放棄一個擁有 userAdminAnyDatabase
角色的使用者之前,請確保至少有一個其他使用者擁有使用者管理許可權。
在這個例子中,我們將放棄測試資料庫中的使用者 “user26″:
use test db.dropUser("user26", {w: "majority", wtimeout: 4000})
輸出:
> db.dropUser("user26", {w: "majority", wtimeout: 4000}); true
(2)createUser
這條命令為指定的資料庫建立一個新的使用者,如下所示:
db.createUser(user, writeConcern)
這裡,user
是一個必填欄位,包含了要建立的使用者的認證和訪問資訊的檔案。可選的欄位writeConcern
包含了對建立操作的寫關注程度。寫入關注的級別可以由可選欄位writeConcern
決定。
如果使用者已經存在於資料庫中,createUser
將返回一個重複的使用者錯誤。
你可以在測試資料庫中建立一個新的使用者,方法如下:
use test db.createUser( { user: "user26", pwd: "myuser123", roles: [ "readWrite" ] } );
輸出結果如下:
Successfully added user: { "user" : "user26", "roles" : [ "readWrite", "dbAdmin" ] }
(3)grantRolesToUser
你可以利用這個命令來授予使用者額外的角色。要使用它,你需要記住以下語法:
db.runCommand( { grantRolesToUser: "<user>", roles: [ <roles> ], writeConcern: { <write concern> }, comment: <any> } )
你可以在上面提到的角色中指定使用者定義的和內建的角色。如果你想指定一個存在於 grantRolesToUser
執行的同一個資料庫中的角色,你可以用一個檔案來指定這個角色,如下所述:
{ role: "<role>", db: "<database>" }
或者,你可以簡單地用角色的名稱來指定角色。比如說:
"readWrite"
如果你想指定存在於不同資料庫中的角色,你就必須用不同的檔案來指定這個角色。
要在一個資料庫上授予一個角色,你需要在指定的資料庫上使用grantRole
動作。
這裡有一個例子可以讓你清楚地瞭解到。以產品資料庫中的使用者productUser00為例,其角色如下。
"roles" : [ { "role" : "assetsWriter", "db" : "assets" } ]
grantRolesToUser
操作為 “productUser00 “提供股票資料庫的 readWrite
角色和產品資料庫的讀取角色。
use products db.runCommand({ grantRolesToUser: "productUser00", roles: [ { role: "readWrite", db: "stock"}, "read" ], writeConcern: { w: "majority" , wtimeout: 2000 } })
產品資料庫中的使用者productUser00現在擁有以下角色:
"roles" : [ { "role" : "assetsWriter", "db" : "assets" }, { "role" : "readWrite", "db" : "stock" }, { "role" : "read", "db" : "products" } ]
(4)usersInfo
你可以使用 usersInfo
命令來返回一個或多個使用者的資訊。下面是語法:
db.runCommand( { usersInfo: <various>, showCredentials: <Boolean>, showCustomData: <Boolean>, showPrivileges: <Boolean>, showAuthenticationRestrictions: <Boolean>, filter: <document>, comment: <any> } ) { usersInfo: <various> }
在訪問方面,使用者總是可以檢視自己的資訊。要看另一個使用者的資訊,執行命令的使用者必須有包括在另一個使用者的資料庫中 viewUser
的動作的許可權。
在執行 userInfo
命令時,根據指定的選項,你可以獲得以下資訊。
{ "users" : [ { "_id" : "<db>.<username>", "userId" : <UUID>, // Starting in MongoDB 4.0.9 "user" : "<username>", "db" : "<db>", "mechanisms" : [ ... ], // Starting in MongoDB 4.0 "customData" : <document>, "roles" : [ ... ], "credentials": { ... }, // only if showCredentials: true "inheritedRoles" : [ ... ], // only if showPrivileges: true or showAuthenticationRestrictions: true "inheritedPrivileges" : [ ... ], // only if showPrivileges: true or showAuthenticationRestrictions: true "inheritedAuthenticationRestrictions" : [ ] // only if showPrivileges: true or showAuthenticationRestrictions: true "authenticationRestrictions" : [ ... ] // only if showAuthenticationRestrictions: true }, ], "ok" : 1 }
現在你已經對使用 usersInfo
命令可以完成的任務有了大致的瞭解,接下來可能會出現的明顯的問題是,在檢視特定的使用者和多個使用者時,什麼命令會很方便?
這裡有兩個方便的例子來說明這一點。
要檢視特定使用者的具體許可權和資訊,而不是證書,對於 “office “資料庫中定義的使用者 “Anthony”,執行以下命令。
db.runCommand( { usersInfo: { user: "Anthony", db: "office" }, showPrivileges: true } )
如果你想檢視當前資料庫中的一個使用者,你只能通過名字來提及該使用者。例如,如果你在主資料庫中,主資料庫中存在一個名為 “Timothy “的使用者,你可以執行以下命令。
db.getSiblingDB("home").runCommand( { usersInfo: "Timothy", showPrivileges: true } )
接下來,如果你想檢視不同使用者的資訊,你可以使用一個陣列。你可以包括可選的欄位 showCredentials
和 showPrivileges
,或者你可以選擇不包括它們。這就是該命令的樣子。
db.runCommand({ usersInfo: [ { user: "Anthony", db: "office" }, { user: "Timothy", db: "home" } ], showPrivileges: true })
(5)revokeRolesFromUser
你可以利用 revokeRolesFromUser
命令,從存在角色的資料庫中的使用者身上刪除一個或多個角色。 revokeRolesFromUser
命令的語法如下:
db.runCommand( { revokeRolesFromUser: "<user>", roles: [ { role: "<role>", db: "<database>" } | "<role>", ], writeConcern: { <write concern> }, comment: <any> } )
在上面提到的語法中,你可以在 roles
欄位中指定使用者定義的和內建的角色。與 grantRolesToUser
命令類似,你可以在檔案中指定你要撤銷的角色,或者使用它的名字。
為了成功執行 revokeRolesFromUser
命令,你需要在指定的資料庫上有 revokeRole
動作。
這裡有一個例子來說明這個問題。產品資料庫中的 productUser00
實體有以下角色:
"roles" : [ { "role" : "assetsWriter", "db" : "assets" }, { "role" : "readWrite", "db" : "stock" }, { "role" : "read", "db" : "products" } ]
下面的 revokeRolesFromUser
命令將刪除使用者的兩個角色: products
的 “read “角色和 “assets “資料庫的 assetsWriter
角色:
use products db.runCommand( { revokeRolesFromUser: "productUser00", roles: [ { role: "AssetsWriter", db: "assets" }, "read" ], writeConcern: { w: "majority" } } )
產品資料庫中的使用者 “productUser00 “現在只有一個剩餘角色:
"roles" : [ { "role" : "readWrite", "db" : "stock" } ]
角色管理命令
角色授予使用者對資源的訪問權。管理員可以使用幾個內建角色來控制對MongoDB系統的訪問。如果這些角色沒有涵蓋所需的許可權,你甚至可以進一步在某個資料庫中建立新的角色。
(1)DropRole
通過 dropRole
命令,你可以從執行該命令的資料庫中刪除一個使用者定義的角色。要執行這個命令,請使用以下語法:
db.runCommand( { dropRole: "<role>", writeConcern: { <write concern> }, comment: <any> } )
為了成功執行,你必須在指定的資料庫上有 dropRole
操作。以下操作將從 “產品 “資料庫中刪除 writeTags
角色:
use products db.runCommand( { dropRole: "writeTags", writeConcern: { w: "majority" } } )
(2)createRole
你可以利用 createRole
命令來建立一個角色並指定其許可權。該角色將適用於你選擇執行該命令的資料庫。如果該角色已經存在於資料庫中, createRole
命令將返回一個重複的角色錯誤。
要執行這個命令,請按照給定的語法進行。
db.adminCommand( { createRole: "<new role>", privileges: [ { resource: { <resource> }, actions: [ "<action>", ... ] }, ], roles: [ { role: "<role>", db: "<database>" } | "<role>", ], authenticationRestrictions: [ { clientSource: ["<IP>" | "<CIDR range>", ...], serverAddress: ["<IP>" | "<CIDR range>", ...] }, ], writeConcern: <write concern document>, comment: <any> } )
一個角色的許可權將適用於建立該角色的資料庫。角色可以從其資料庫中的其他角色繼承許可權。例如,一個在 “admin “資料庫上建立的角色可以包括適用於叢集或所有資料庫的許可權。它也可以從其他資料庫中的角色繼承許可權。
要在一個資料庫中建立一個角色,你需要具備兩點:
- 在該資料庫上的
grantRole
動作,提及新角色的許可權,以及提及要繼承的角色。 - 在該資料庫資源上進行
createRole
操作。
下面的 createRole
命令將在使用者資料庫上建立一個clusterAdmin
角色。
db.adminCommand({ createRole: "clusterAdmin", privileges: [ { resource: { cluster: true }, actions: [ "addShard" ] }, { resource: { db: "config", collection: "" }, actions: [ "find", "remove" ] }, { resource: { db: "users", collection: "usersCollection" }, actions: [ "update", "insert" ] }, { resource: { db: "", collection: "" }, actions: [ "find" ] } ], roles: [ { role: "read", db: "user" } ], writeConcern: { w: "majority" , wtimeout: 5000 } })
(3)grantRolesToRole
通過 grantRolesToRole
命令,你可以將角色授予一個使用者定義的角色。 grantRolesToRole
命令將影響執行該命令的資料庫中的角色。
這個 grantRolesToRole
命令的語法如下:
db.runCommand( { grantRolesToRole: "<role>", roles: [ { role: "<role>", db: "<database>" }, ], writeConcern: { <write concern> }, comment: <any> } )
訪問許可權與 grantRolesToUser
命令類似–你需要在資料庫上有一個grantRole
動作才能正確執行該命令。
在下面的例子中,你可以使用 grantRolesToUser
命令來更新 “products “資料庫中的productsReader
角色,使其繼承 productsWriter
角色的許可權:
use products db.runCommand( { grantRolesToRole: "productsReader", roles: [ "productsWriter" ], writeConcern: { w: "majority" , wtimeout: 5000 } } )
(4)revokePrivilegesFromRole
你可以使用 revokePrivilegesFromRole
來從執行命令的資料庫上的使用者定義的角色中移除指定的許可權。為了正確執行,你需要記住以下語法:
db.runCommand( { revokePrivilegesFromRole: "<role>", privileges: [ { resource: { <resource> }, actions: [ "<action>", ... ] }, ], writeConcern: <write concern document>, comment: <any> } )
要撤銷一個許可權,”resource document”模式必須與該許可權的 “resource”欄位匹配。“actions”欄位可以是完全匹配,也可以是一個子集。
例如,考慮產品資料庫中的角色 manageRole
,它有以下特權,指定 “managers”資料庫為資源:
{ "resource" : { "db" : "managers", "collection" : "" }, "actions" : [ "insert", "remove" ] }
你不能只從管理者資料庫中的一個集合中撤銷 “insert”或 “remove”操作。以下操作不會導致角色的改變。
use managers db.runCommand( { revokePrivilegesFromRole: "manageRole", privileges: [ { resource : { db : "managers", collection : "kiosks" }, actions : [ "insert", "remove" ] } ] } )
db.runCommand( { revokePrivilegesFromRole: "manageRole", privileges: [ { resource : { db : "managers", collection : "kiosks" }, actions : [ "insert" ] } ] } )
要撤銷角色 manageRole
的 “insert”和/或 “remove”操作,你需要與資原始檔完全匹配。例如,下面的操作只撤銷了現有許可權中的 “remove”操作。
use managers db.runCommand( { revokePrivilegesFromRole: "manageRole", privileges: [ { resource : { db : "managers", collection : "" }, actions : [ "remove" ] } ] } )
下面的操作將從管理人員資料庫中的 “executive”角色中刪除多個許可權:
use managers db.runCommand( { revokePrivilegesFromRole: "executive", privileges: [ { resource: { db: "managers", collection: "" }, actions: [ "insert", "remove", "find" ] }, { resource: { db: "managers", collection: "partners" }, actions: [ "update" ] } ], writeConcern: { w: "majority" } } )
(5)rolesInfo
rolesInfo
命令將返回指定角色的許可權和繼承資訊,包括內建和使用者定義的角色。你也可以利用rolesInfo
命令來檢索一個資料庫的所有角色範圍。
為了正確的執行,請遵循這個語法:
db.runCommand( { rolesInfo: { role: <name>, db: <db> }, showPrivileges: <Boolean>, showBuiltinRoles: <Boolean>, comment: <any> } )
要從當前資料庫中返回一個角色的資訊,你可以按以下方式指定其名稱。
{ rolesInfo: "<rolename>" }
為了從另一個資料庫返回一個角色的資訊,你可以用一個提到該角色和資料庫的檔案來提到該角色:
{ rolesInfo: { role: "<rolename>", db: "<database>" } }
例如,下面的命令返回在管理人員資料庫中定義的角色執行者的角色繼承資訊。
db.runCommand( { rolesInfo: { role: "executive", db: "managers" } } )
接下來這條命令將返回角色繼承資訊:在執行命令的資料庫上的 accountManager
。
db.runCommand( { rolesInfo: "accountManager" } )
下面的命令將返回管理人員資料庫中定義的角色 “executive “的許可權和角色繼承權。
db.runCommand( { rolesInfo: { role: "executive", db: "managers" }, showPrivileges: true } )
要提到多個角色,你可以使用一個陣列。你也可以在陣列中以字串或文件的形式提到每個角色。
只有當角色存在於執行命令的資料庫中時,你才應該使用字串。
{ rolesInfo: [ "<rolename>", { role: "<rolename>", db: "<database>" }, ] }
例如,下面的命令將返回三個不同資料庫中三個角色的資訊。
db.runCommand( { rolesInfo: [ { role: "executive", db: "managers" }, { role: "accounts", db: "departments" }, { role: "administrator", db: "products" } ] } )
你可以通過以下方式獲得許可權和角色的繼承權。
db.runCommand( { rolesInfo: [ { role: "executive", db: "managers" }, { role: "accounts", db: "departments" }, { role: "administrator", db: "products" } ], showPrivileges: true } )
嵌入MongoDB文件以提高效能
像MongoDB這樣的文件資料庫可以讓你根據你的需要定義你的模式。為了在MongoDB中建立最佳模式,你可以對文件進行巢狀。因此,你可以建立一個與你的用例相匹配的資料模型,而不是將你的應用與一個資料模型相匹配。
嵌入檔案讓你儲存相關的資料,你可以一起訪問。在為MongoDB設計模式時,建議你預設嵌入文件。只有在值得的時候才使用資料庫側或應用程式側的連線和引用。
確保工作負載可以根據需要經常檢索文件。同時,文件也應該有它需要的所有資料。這對你的應用程式的卓越效能是至關重要的:
下面,你會發現一些不同的模式來嵌入文件。
嵌入文件模式
你可以用它來將甚至複雜的子結構嵌入到它們所使用的文件中。在單個文件中嵌入連線的資料可以減少獲取資料所需的讀取操作的數量。一般來說,你應該構建你的模式,使你的應用程式在一次讀取操作中收到所有需要的資訊。因此,這裡要記住的規則是,一起使用的東西應該一起儲存。
嵌入子集模式
嵌入子集模式是一種混合情況。你會把它用在一長串相關專案的單獨集合上,你可以把其中一些專案保留在手邊進行顯示。
這裡有一個例子,列出了電影評論。
> db.movie.findOne() { _id: 321475, title: "The Dark Knight" } > db.review.find({movie_id: 321475}) { _id: 264579, movie_id: 321475, stars: 4 text: "Amazing" } { _id: 375684, movie_id: 321475, stars:5, text: "Mindblowing" }
現在,想象一下有一千個類似的評論,但你只打算在放映電影時顯示最近的兩個。在這種情況下,將這個子集作為一個列表儲存在電影文件中是有意義的。
> db.movie.findOne({_id: 321475}) { _id: 321475, title: "The Dark Knight", recent_reviews: [ {_id: 264579, stars: 4, text: "Amazing"}, {_id: 375684, stars: 5, text: "Mindblowing"} ] }
簡單地說,如果你經常訪問相關專案的一個子集,確保你嵌入它。
獨立訪問
你可能想把子檔案儲存在它們的集合中,把它們與它們的父集合分開。
例如,以一個公司的產品系列為例。如果公司銷售的是一小部分產品,你可能想把它們儲存在公司檔案中。但如果你想在不同的公司之間重複使用它們,或者直接通過它們的庫存單位(SKU)來訪問它們,你也會想把它們儲存在它們的集合中。
如果你獨立地操作或訪問一個實體,為了最好的實踐,做一個集合來單獨儲存它。
無界列表
在它們的文件中儲存相關資訊的短列表有一個缺點。如果你的列表繼續無限制地增長,你就不應該把它放在一個文件中。這是因為你不會有能力支援很長時間。
這有兩個原因。首先,MongoDB對單個文件的大小有限制。第二,如果你訪問文件的頻率太高,你會看到記憶體使用不受控制的負面結果。
簡單地說,如果一個列表開始無限制地增長,就做一個集合來單獨儲存它。
擴充套件參考模式
擴充套件參考模式與子集模式一樣。它也優化了你經常訪問儲存在文件上的資訊。
在這裡,當一個文件引用另一個存在於同一集合中的文件時,而不是一個列表,它被利用。同時,它也儲存了其他文件的一些欄位,以便隨時訪問。
比如說:
> db.movie.findOne({_id: 245434}) { _id: 245434, title: "Mission Impossible 4 - Ghost Protocol", studio_id: 924935, studio_name: "Paramount Pictures" }
正如你所看到的,”the studio_id “被儲存起來,以便你可以查詢更多關於創作該影片的工作室的資訊。但為了簡單起見,工作室的名字也被複制到了這個文件中。
要想定期從修改過的文件中嵌入資訊,記得在修改時更新你複製了該資訊的文件。換句話說,如果你經常從一個被引用的檔案中訪問一些欄位,就把它們嵌入。
如何監控MongoDB
你可以使用一些監控工具來除錯長的API呼叫,緩慢的資料庫查詢,長的外部URL請求,等等。你甚至可以利用命令來提高資料庫效能。你也可以用它們來檢查你的資料庫例項的健康狀況。
為什麼要監控MongoDB資料庫?
資料庫管理規劃的一個關鍵方面是監控你的叢集的效能和健康。MongoDB Atlas通過其容錯/擴充套件能力處理了大部分的管理工作。
儘管如此,使用者需要知道如何跟蹤叢集。他們還應該知道如何在遇到危機之前擴充套件或調整他們需要的東西。
通過監控MongoDB資料庫,你可以。
- 觀察資源的利用情況。
- 瞭解你的資料庫的當前容量。
- 反應和檢測實時問題,以增強你的應用堆疊。
- 觀察是否存在效能問題和異常行為。
- 與你的治理/資料保護和服務級別協議(SLA)要求保持一致。
需要監測的關鍵指標
在監控MongoDB時,有四個關鍵方面你需要記住。
1. MongoDB硬體指標
以下是監控硬體的主要指標。
(1)歸一化程序CPU
它被定義為CPU用於維護MongoDB程序的應用軟體的時間百分比。
你可以通過將其除以CPU核的數量,將其擴充套件到0-100%的範圍。它包括核心和使用者等模組所利用的CPU。
高的核心CPU可能表明通過作業系統操作耗盡了CPU。但與MongoDB操作相關的使用者可能是CPU耗盡的根本原因。
(2)正常化的系統CPU
這是CPU花在服務於這個MongoDB程序的系統呼叫上的時間百分比。你可以通過將它除以CPU核的數量,將其擴充套件到0-100%的範圍。它還涵蓋了iowait、使用者、核心、steal等模組使用的CPU。
使用者CPU或高核心可能顯示通過MongoDB操作(軟體)的CPU耗盡。高iowait可能與儲存耗盡導致CPU耗盡有關。
(3)磁碟IOPS
磁碟IOPS是MongoDB的磁碟分割槽上每秒平均消耗的IO操作。
(4)磁碟延時
這是MongoDB中磁碟分割槽的讀寫磁碟延遲,單位是毫秒。高值(>500ms)表明儲存層可能影響MongoDB的效能。
(5)系統記憶體
使用系統記憶體來描述使用的實體記憶體位元組與可用的自由空間。
可用指標近似於系統記憶體的可用位元組數。你可以用它來執行新的應用程式,不需要交換。
(6)可用磁碟空間
這被定義為MongoDB的磁碟分割槽上的可用磁碟空間的總位元組數。MongoDB Atlas提供了基於此指標的自動擴充套件功能。
(7)交換使用情況
你可以利用交換使用圖來描述有多少記憶體被放在交換裝置上。在這個圖表中,一個高使用量的指標表明,交換正在被利用。這表明記憶體對於當前的工作負載來說是配置不足的。
2. MongoDB叢集的連線和操作指標
下面是操作和連線度量的主要指標。
(1)操作執行時間
在選定的樣本期間執行的平均操作時間(寫和讀操作)。
(2)操作次數
這是在選定的樣本期間,每秒執行的平均操作率。運算元圖/指標顯示操作型別的細分和例項的速度。
(3)連線數
這個指標指的是例項的開放連線數。高的峰值或數字可能指向一個次優的連線策略,無論是從無響應的伺服器還是客戶端。
(4)查詢目標和查詢執行器
這是在選定的掃描檔案的樣本期間,每秒的平均速率。對於查詢執行者,這是在查詢計劃評估和查詢期間。查詢目標顯示掃描的檔案數量和返回的檔案數量之間的比率。
一個高的數字比率指向次優操作。這些操作掃描了大量的文件以返回較小的部分。
(5)掃描和順序
它描述了在選擇的查詢樣本期中每秒的平均速率。它返回排序的結果,不能使用索引執行排序操作。
(6)佇列
佇列可以描述等待鎖的操作的數量,無論是寫還是讀。高佇列可能描繪了存在不理想的模式設計。它也可能表明有衝突的寫入路徑,推動了對資料庫資源的高度競爭。
3. MongoDB副本集指標
以下是副本集監控的主要指標。
(1)副本集Oplog視窗
這個指標列出了主站的副本集Oplog中可用的大約小時數。如果一個輔助系統的滯後時間超過這個數量,它就不能跟上,將需要完全重新同步。
(2)副本集滯後
副本集滯後被定義為一個輔助節點在寫操作中落後於主節點的大約秒數。高的副本集滯後將指向一個在副本集中面臨困難的輔助節點。考慮到連線的讀/寫問題,它可能會影響你的操作的延遲。
(3)副本集餘量
這個指標指的是主副本集的oplog視窗和輔助副本集的滯後之間的差異。如果這個值為零,可能會導致輔助系統進入RECOVERING模式。
(4)Opcounters -repl
Opcounters -repl 被定義為在選擇的樣本期每秒執行的副本集操作的平均速率。通過 opcounters -graph/metric,你可以看一下指定例項的操作速度和操作型別的細分。
(5)Oplog GB/小時
這被定義為主系統每小時產生的OPLOG的平均速率。oplog的高意外量可能指向一個高度不充分的寫入工作負載或模式設計問題。
MongoDB效能監控工具
MongoDB在Cloud Manager、Atlas和Ops Manager中擁有內建的使用者介面工具,用於效能跟蹤。它還提供了一些獨立的命令和工具來檢視更多基於原始的資料。我們將談論一些你可以從有許可權和適當角色的主機上執行的工具,以檢查你的環境。
mongotop
你可以利用這個命令來跟蹤MongoDB例項在每個集合中花費的寫入和讀取資料的時間。使用下面的語法:
mongotop <options> <connection-string> <polling-interval in seconds>
rs.status()
該命令返回複製集的狀態。它是從執行該方法的成員的角度來執行的。
mongostat
你可以使用 mongostat
命令來快速瞭解你的MongoDB伺服器例項的狀態。為了獲得最佳輸出,你可以用它來觀察單個例項的特定事件,因為它提供了一個實時檢視。
利用這個命令來監控基本的伺服器統計資料,如鎖佇列、操作分解、MongoDB記憶體統計和連線/網路。
mongostat <options> <connection-string> <polling interval in seconds>
dbStats
該命令返回特定資料庫的儲存統計資料,例如索引的數量及其大小,總的集合資料與儲存大小,以及與集合相關的統計資料(集合和檔案的數量)。
db.serverStatus()
你可以利用 db.serverStatus()
命令來了解資料庫的狀態。它給你一個代表當前例項指標計數器的檔案。每隔一段時間執行這個命令來整理關於例項的統計資料。
collStats
collStats
命令收集類似於 dbStats
在集合級別提供的統計資料。它的輸出包括集合中物件的數量、集合所消耗的磁碟空間、集合的大小以及關於特定集合的索引的資訊。
你可以使用所有這些命令來提供資料庫伺服器的實時報告和監控,讓你監控資料庫的效能和錯誤,並協助做出明智的決策來完善資料庫。
如何刪除MongoDB資料庫
要放棄一個你在MongoDB中建立的資料庫,你需要通過use關鍵字連線到它。
假設你建立了一個名為 “Engineers”的資料庫。為了連線到該資料庫,你將使用以下命令:
use Engineers
接下來,輸入 db.dropDatabase()
來擺脫這個資料庫。執行後,這是你可以期待的結果。
{ "dropped" : "Engineers", "ok" : 1 }
你可以執行 showdbs
命令來驗證資料庫是否仍然存在。
小結
為了從MongoDB中榨取每一滴價值,你必須對基礎知識有深刻的理解。因此,對MongoDB資料庫瞭如指掌是非常關鍵的。這就要求你首先熟悉建立資料庫的方法。
在這篇文章中,我們闡明瞭在MongoDB中建立資料庫的不同方法,然後詳細介紹了一些靈巧的MongoDB命令,讓你在資料庫中保持領先地位。最後,我們通過討論如何利用MongoDB中的嵌入式文件和效能監控工具來確保你的工作流程以最高效率運作來結束討論。
評論留言