文檔
概述
文檔是MongoDB的核心概念,是數據的基本單元,非常類似於關系數據庫中的行。在MongoDB中,文檔表示為鍵值對的一個有序集。MongoDB使用Javascript shell,文檔的表示一般使用Javascript里面的對象的樣式來標記,如下:
1 {"title":"hello!"} 2 {"title":"hello!","recommend":5} 3 {"title":"hello!","recommend":5,"author":{"firstname":"paul","lastname":"frank"}}
從上面的例子可以看到,文檔的值有不同的數據類型,甚至可以是一個完整的內嵌文檔(最后一個示例的author是有一個完整的文檔表示的,文檔里面定義了firstname和lastname。當然還可以包含更多其他信息甚至於在內嵌文檔中還可以有內嵌文檔)。
說明
文檔區分大小寫和數據類型,所以以下兩組文檔是不同的:
1 {"recommend":"5"} 2 {"recommend":5} 3 4 {"Recommend":"5"} 5 {"recommend":"5"}
MongoDB的文檔不能有重復的鍵。下面的文檔是非法的:
1 {"title":"hello!","title":"Mongo"}
操作
創建
創建文檔非常簡單,通過插入語句就能向數據庫中創建一個文檔記錄。
1 > db.blogs.insert({"title":"hello!"})
如果在執行這條語句之前,數據庫和blogs集合並沒有創建,會分別創建數據庫和集合,同時插入文檔。
刪除
1 > db.blogs.remove() // 刪除集合中所有文檔。 2 > db.blogs.remove({"title":"hello!"}) // 刪除指定條件的文檔,當前語句刪除"title"為"hello!"的文檔。
集合
集合是一組文檔的集,相當於關系型數據庫中的數據表。
動態模式
集合是動態模式的。什么意思呢?具體來說就是一個集合里面的文檔可以是各式各樣的。舉例來說,下面的兩種文檔完全可以存儲在同一個集合里面:
1 {"title":"hello!"} 2 {"recommend":5}
可以看出,上面兩個文檔不僅值得類型不同,連鍵也完全不一樣。這和關系型數據庫中一個表中只能存放相同模型的數據結構顯得很不一樣。但是這也就產生了一個問題:既然一個集合中可以存放任意的文檔,那么多個集合的存在還有什么必要性呢?這其實可以和關系型數據表可以對應起來理解,我們可以創建一張表容納下上面提到的title和recommend列,但是總有一個列是NULL的。這還僅僅是兩個列的情況,如果出現無數的列,那么這種情況就非常糟糕了。所以不難想出一個數據庫中存在多個集合的原因應該至少有如下幾點:
-
數據混亂。開發人員要區分每次查詢只返回特定類型的文檔,或者把這個區分交給處理查詢結果的應用程序來處理。這對於開發和維護來說都會帶來很大的麻煩。
-
性能。分別在不同的集合上查詢要比在一個集合中去查詢不同數據快得多。
-
數據更集中。同種類型的文檔放在一個集合里,數據更加集中,查詢數據時。需要的磁盤尋道操作更少,效率更高。
-
更高效的利用索引。索引是按照集合來定義的。創建索引時,需要使用文檔的附加結構。在一個集合中只放入一種類型的文檔,可以更有效的對集合進行索引。
常用命令
-
show collections 查看當前數據庫中存在哪些集合,將展示集合的名稱列表。如下圖所示:
-
help() 獲取集合上的可執行命令的列表。執行語句如下:
1 db.users.help() -
insert(obj) 向集合中插入一個文檔。
-
drop() 刪除當前集合,刪除之后不可恢復。
-
dropIndex(index) 刪除集合上的索引,參數為空時,刪除所有索引(除了_id上的索引)
-
ensureIndex(keypattern[,options]) 創建索引
-
update(query,object[,upsert_bool,multi_bool]) 更新集合中滿足條件的文檔
-
find([query,fields]) 根據條件查詢滿足條件的文檔
當然還有很多命令在這里沒有列出,但是可以通過help()命令輕松的查看能在集合上執行的命令。
數據庫
多個文檔構成集合,多個集合組成數據庫。一個MongoDB實例可以承載多個數據庫,每個數據庫可以擁有0到多個集合。下圖所示是我的機器上用到的數據庫的本地文件:

說明
-
每個數據庫有相應的數據文件和命名空間文件。文件的前綴是數據庫的名稱,后綴.ns表示命名空間文件,后綴以.0、.1等數字結尾的,表示數據文件。
-
數據文件的大小從64MB開始(這是在64位Windows Server 2012上看到的結果,其他環境可能有些差異),新的數據文件比上一個文件大一倍。所以能看到,chen.0的大小是64MB,chen.1的大小是128MB,chen.2是256MB。
-
文件使用MMAP進行內存映射,會將所有的數據文件映射到內存中,但是只是虛擬內存,只有訪問到這塊數據時才會交換到物力內存中。
-
每個數據文件會被分成一個一個的數據塊,塊與塊之間用雙向鏈表鏈接。
-
在命名空間文件中,保存了每個命名空間的存儲信息元數據,包括其大小、塊數、第一塊的位置、最后一塊的位置、被刪除的塊的鏈表以及索引信息。
常用命令
-
show dbs 查看當前MongoDB實例中存在的數據庫,展示數據庫名稱列表和數據庫占用的磁盤空間大小。如下圖所示:

-
db 檢驗當前正在使用哪個數據庫。如下圖所示:

-
use xxx 切換當前使用的數據庫。當use一個不存在的數據庫的時候,不會立刻創建數據庫的數據文件和命名空間文件,而是會在第一次向數據庫中插入一個文件的時候才去創建對應的數據庫。在這一點上,集合也有類似的特性。
-
db.dropDatabase() 刪除當前使用的數據庫。在刪除當前使用的數據庫之后,db任然指向被刪除的那個數據庫名稱,可以通過use切換;如果不切換就做數據插入操作,會重新建立相同名字的一個數據庫,但是已經不是原來的數據庫了,盡管有相同的名稱,也有可能有相同的集合和文檔。
參考資料:
https://docs.mongodb.org/manual/
《MongoDB權威指南》(第二版)
