MongoDB數據類型
MongoDB支持多種數據類型作為文檔中的值,MongoDB通過BSON(Binary JSON)來描述和存放數據。BSON是一種可進行二進制序列化的、類JSON格式的文檔對象。通過BSON, MongoDB可以方便地存儲無模式(schema)數據。
一、基本數據類型
MongoDB中的文檔與JAVAScript中的對象非常相似,因而可認為它類似于JSON。JSON是一種簡單的數據表示方式,它僅包含6種數據類型(null, 布爾、數值、字符串、數組和對象)這幾種數據類型,所以JSON的表達能力有一定的局限性,比如,JSON沒有日期類型,JSON只有一種數值類型,無法區分浮點數和整數。
MongoDB在保留JSON的鍵值對的基礎上,添加了一些其它數據類型,且在不同的編程語言下,這些類型的表示也是有所差異的。下面介紹MongoDB支持的通用類型,以及如何使用這些類型。
- null: 用于表示空值或不存在的字段,例如{"x": null}
- 布爾型: 布爾型有兩個值true或false, 例如: {"x": true}
- 數值: shell默認使用64位浮點數值,例如:{"x": 3.14}, {"x": 3}
- 對于整型值,可以使用NumberInt類(表示4字節帶符號整數)或NumberLong類(表示8字節帶符號整數),例如: {"x": NumberInt("13")}, {"x": NumberLong(30)}
- 字符串: UTF-8字符串伏特加不上課表示為字符串類型的數據,例如:{"x":"Taobao"};
- 日期: 日期被存儲為新紀元以來經歷的毫秒數,不存儲時區, 例如: {"date": new Date()}
- 正則表達式:查詢時,使用正則表達式作為限定條件,語法也與JavaScript的正則表達式語法相同,例如:{"x": /document/i}
- 數組:數據列表或數據集可以表示為數組,例如:{"category":["日用品","零食","飲料"]}
- 內嵌文檔:文檔可以嵌套其它文檔,被嵌套的文檔作為父文檔的值,例如:{"doc": {”name":"張三", "age": 20}}
- 對象id: 對象id是一個24字節的ID, 是文檔的唯一標識
- 二進制數據:二進制數據是任意字節的字符串。它不能直接在shell中使用。如果將非UTF-8字符保存到數據庫中,二進制數據是唯一的方式。
- 代碼:查詢和文檔中可以包含任意JavaScript代碼,例如:{"f": function(){/*...*/}}
二、日期
在JavaScript中,Date類可以作為MongoDB的日期類型。創建日期對象時,就當使用new Date(...) 而非Date(...)。如將構造函數(constructor)作為函數進行調用(即不使用new的方式),返回的是日期的字符串表示,而非日期(Date)對象。這個結果與MongoDB無關,是JavaScript的工作機制決定的。
如果不注意這一點,沒有使用構造函數的方式將會得到一堆混亂的日期對象和日期的字符串。由于日期和字符串之間無法匹配,所以在執行刪除、更新及查詢時操作時會導致很多問題出現。
三、數組
數組是一組值,它既能作為有序對象(如列表,棧,隊列),也能作為無序對象,如數據集來操作。
實際上,常規的鍵/值對支持的所有值都可以作為數組的值,數組中甚至可以嵌套數據。
文檔中的數據在MongoDB中有個奇妙的特性,就是它能夠理解其結構,并知道如何深入數組內部對其內容進行操作。這樣就能使用數據內容對數據進行查詢和構建索引。
四、嵌套文檔
文檔可以作為鍵的值,這樣的文檔就是`內嵌文檔`。使用內嵌文檔時,可以使數據組織方式更加自然,不用非得存儲成扁平結構的鍵值對。
例如,用一個文檔來表示員工的基本信息:
{
"name": "風清揚",
"age": 65,
"gender": "男",
"kongfu": "獨孤九劍",
"address_info":{
"address": "華山",
"location":"江西省南昌市",
"mobile":"13888888888",
"Apprentice": ["令狐沖","任盈盈"]
}
}
同數據一樣,MongoDB也能夠深入理解內嵌文檔的內部結構,并能夠深入其中構建索引、執行查詢或者更新操作。
五、_id和ObjectId
MongoDB中存儲的文檔必須有一個"_id"鍵,這個鍵的值可以是任何類型的,默認是個ObjectId的對象。在一個集合里面,每個文檔都有一個唯一的"_id", 確保集合中的每一個文檔被唯一的標識。如果是兩個集合的話,可以有"_id"的值相同,但是在一個集合內部不能有重復的"_id"值。
5.1. ObjectId
ObjectId是“_id"的默認類型。它設計成輕量型的,不同的機器都能用全局唯一的同種方法方便地生成它。這是MongoDB采用的ObjectId, 而不是其它比較常規的做法(如MySQL中的自增長列)的主要原因,因為在多個服務器上同步自增長費力費時。MongoDB的設計之初就是為了支持分布式的數據存儲,所以能夠在分布式的環境中生成唯一的標識符顯得很重要。
ObjectId使用12個字節的存儲空間,是一個由24個十六進制的數字組成的字符串(每個字節可以存儲兩個十六進制數字)。它的主要構成如下:
- 前 8 個十六進制數字表示創建 unix 時間戳,格林尼治時間 UTC 時間,比北京時間晚了 8 個小時
- 接下來的 6 個十六進制數字是機器標識碼: 通常是機器主機名的散列值
- 緊接的4個十六進制數字由進程 id 組成 PID:產生ObjectId進行的PID
- 最后6個十六進制數字是隨機數: 確保相同進行同一秒產生的ObjectId是不一樣的
ObjectId構成
5.2.自動生成"_id"
如果插入文檔時沒有"_id"鍵, 系統會自動創建一個,可以由MongoDB服務器來創建的, 但通常會在客戶端由驅動程序完成。將工作交給客戶端來處理有效減輕了服務器的壓力。
附錄:常見MongoDB數據類型
常見MongoDB數據類型表