本博客參考MongoDB4.2官方文檔。javascript
MongoDB的文檔相似於JSON,JSON是一種簡單的表示數據的方式,僅包含6種數據類型,分別是:null、布爾、數字、字符串、數組和對象。java
雖然這些類型的表現已經足夠強大,可是對於絕大多數應用來講還須要另一些不可或缺的類型。例如,日期類型、數字類型(只有一種,無法區分整型和浮點)、正則表達式等。正則表達式
MongoDB在保留JSON基本的鍵值對特性的基礎上,添加了其餘一些數據類型。在不一樣的編程語言下這些類型的表示有些差別。 下面列出MongoDB一般支持的一些類型,同時說明了在shell中這些類型的表示方法。shell
每種BSON類型都具備整數和字符串標識符,以下表所示:數據庫
類型 | 整數 | 別名 | 備註 | 說明 |
---|---|---|---|---|
Double | 1 | double | shell中的數字類型 | 64位浮點數 |
String | 2 | string | 字符串類型 | |
Object | 3 | object | 對象類型 | |
Array | 4 | array | 數組類型 | |
Binary data | 5 | binData | shell中不可用 | 二進制數據類型 |
Undefined | 6 | undefined | 已過期 | 未定義類型 |
ObjectId | 7 | objectId | 對象id類型 | |
Boolean | 8 | bool | 布爾類型 | |
Date | 9 | date | 日期類型 | |
Null | 10 | null | 用於表示空值或者不存在的字段 | |
Regular Expression | 11 | regex | 正則表達式類型 | |
DBPointer | 12 | dbPointer | 已過期 | |
JavaScript | 13 | javascript | JavaScript代碼 | |
Symbol | 14 | symbol | shell中不可用,已過期 | |
JavaScript(with scope) | 15 | javascriptWithScope | 帶做用域的JavaScript代碼 | |
32-bit integer | 16 | int | shell中不可用 | 32位整數 |
Timestamp | 17 | timestamp | 時間戳類型 | |
64-bit integer | 18 | long | shell中不可用 | 64位整數 |
Decimal128 | 19 | decimal | 3.4版本新增 | |
Min key | -1 | minKey | shell中無此類型 | 最小鍵 |
Max key | 127 | maxKey | shell中無此類型 | 最大鍵 |
下面針對一些經常使用的數據類型進行詳細說明。編程
shell中這個類型不可用,由於JavaScript僅支持64位浮點數,因此32位整數會被自動轉換爲爲64位浮點數。數組
shell中也不支持這個類型,shell中會使用一個特殊的內嵌文檔來顯示64位整數。服務器
JavaScript中只有一種數字類型。MongoDB中有3種數字類型,shell必須繞過JavaScript的限制。默認狀況下,shell中的數字都被MongoDB看成是雙精度數。這就意味着若是從數據庫張總得到一個32位整數,修改文檔後,將文檔存回數據庫的時候,這個整數也被轉換成了浮點數,即使是保持這個整數原封不動存回去,也是這樣的。因此儘可能不要在shell下覆蓋整個文檔。編程語言
數字只能表示爲雙精度數,有些64位的整數並不能精確地表示爲64位浮點數。因此要是存入一個64位整數,而後在shell中查看,它會顯示一個內嵌文檔,表示可能不許確。編碼
例如,在集合中存入一個文檔(不是在shell模式下存入的),其中myInterger鍵的值設爲一個64位整數3,而後在shell中查看,以下:
>doc = db.nums.findOn(); { 「_id」 : ObjectId(「4c0beecfd096a2580fe6fa08」), 「myInteger」 : { 「floatApprox」 : 3 } }
內嵌文檔只表示shell顯示的是一個64位浮點數近似表示的64位整數,若內嵌文檔只有一個鍵的話,實際上這個值是準確的。
要是插入的64位整數不能精確地做爲雙精度數顯示,shell會添加兩個鍵,分別是「top」(表示高32位)和「bottom」(表示低32位)。
例如,插入9223372036854775807,shell顯示以下:
>doc = db.nums.findOn(); { 「_id」 : ObjectId(「4c0beecfd096a2580fe6fa10」), 「myInteger」 : { 「floatApprox」 : 9223372036854776000, 「top」 :2147483647, 「bottom」 : 4294967295 } }
floatApprox是一種特殊的內嵌文檔,能夠做爲值和文檔來操做。
>doc.myInteger.floatApprox 3 > doc.myInteger + 1 4
BSON字符串是UTF-8。一般,在序列化和反序列化BSON時,每種編程語言的驅動程序都會從語言的字符串格式轉換爲UTF-8。能夠輕鬆地將大多數國際字符存儲在BSON字符串中。此外,MongoDB的$regex查詢在正則表達式字符串中支持UTF-8。
字符串類型可使用sort()方法進行排序,可是sort()是由C++的strcmpAPI實現的,排序可能會錯誤的處理某些字符。
數組是一組值,既能夠既能夠偶組爲有序對象來操做,也能夠做爲無序對象操做。
數組能夠包含不一樣數據類型的元素,實際上,常規鍵值對支持的值均可以做爲數組的元素,甚至是套嵌數組。
文檔中的數組有個特性,就是MongoDB能理解其結構,並指導如何深刻數組內部對其內容進行操做。這樣就能用內容對數組進行查詢和構建索引了。
MongoDB可使用原子更新修改數組中的內容。
值的集合或者列表能夠表示成數組。
{ 「x」 : [「a」, 「b」, 「c」]}
二進制數據能夠由任意字節的串組成。不過shell中沒法使用。
文檔中也可使用未定義類型undefined。4.2版本中已經顯示過期。
{ 「x」 : unddefined }
ObjectId使用12字節的存儲空間,每一個字節兩位十六進制數字,是一個24位的字符串。
在早期版本中,這些字節是有特定的結構的:開頭的4個字節是標準的Unix時間戳,編碼了重新紀元開始的秒數;接下來的3個字節存儲了機器ID;隨後則是2個字節的進程ID;最後3個字節存儲了進程局部的計數器,每次生成對象ID計數器都會加1。時間戳、機器ID和進程ID組合起來,提供了秒級別的惟一性。時間戳在前,意味着ObjectId大體會按照插入的順序排序。能夠將其做爲索引提升效率,但不是絕對的,只是大體。這4個字節也隱含了文檔建立的時間,絕大多數驅動都會公開一個方法從ObjectId獲取這個信息。前9個字節保證了同一秒不一樣機器不一樣進程產生的ObjectId是惟一的,後3字節就是一個自動增長的計數器,保證了相同進程同一秒產生的ObjectId也是不同的。同一秒鐘容許每一個進程擁有2563(16777216)個不一樣的ObjectId。
當前4.2版本中是這樣介紹的,ObjectId各個段含義以下:
前4個字節的值,表示自Unix紀元以來的秒數。中間5個字節是隨機值。最後3個字節是計數器,以隨機值開始。
{「x」 : objectId() }
使用ObjectId有如下兩個優勢:
> ObjectId("5b4c65a07a88f6e8893b70ef").getTimestamp() ISODate("2018-07-16T09:30:08Z")
MongoDB中存儲的文檔必須有一個「_id」鍵,這個鍵能夠是任何類型的,默認是ObjectId對象。在一個集合中,每一個文檔都有惟一的「_id」值,來確保集合裏面每一個文檔都能被惟一標識。此惟一是在一個集合中保證全局惟一的。
ObjectId是「_id」的默認類型。它設計成輕量型,不一樣的機器都能用全局惟一的同種方法方便地生成它。這是MongoDB採用這種類型的主要緣由。
若是插入文檔的時候沒有「_id」鍵,系統會自動建立一個。這件事能夠由MongoDB服務器來作,也能夠在客戶端由驅動程序完成。
一般會將自動生成_id放在客戶端讓驅動程序來完成,理由以下:
布爾類型有兩個值true和false。
{ 「x」 : true }
日期類型存儲的是從標準紀元開始的毫秒數,不存儲時區。
{「x」 : new Date() }
日期類型存儲的日期大概爲2.9億年。毫秒數爲負值,表示1970年以前的日期。
在JavaScript中,Date對象用作MongoDB的日期類型,建立一個新的Date對象時,調用new Date()而不是Date()。調用Date()實際上會返回對日期的字符串表示,而不是真正的Date對象。這不是MongoDB的特性,而是JavaScript自己的特性。
若是使用錯誤,就會致使日期和字符串混淆,字符串和日期不能互相匹配,最終會給刪除、更新、查詢等不少操做帶來問題。
shell中的日期顯示時使用本地時區設置。日期在數據中是以標準紀元開水的毫秒數的形式存儲的,沒有與之相關的時區信息。
null用於表示空值或者不存在的字段。
{「x」 : null }
文檔中能夠包含正則表達式,採用JavaScript的正則表達式語法。
{ 「x」 : /foobar/i }
文檔中還能夠包含JavaScript代碼。
{「x」: function() { /*…*/} }
shell不支持這種類型。shell將數據庫裏的符號類型轉換成字符串。如今已通過時。
BSON有一個MongoDB內部使用的特殊的時間戳類型,和常的日期類型沒有關係。
時間戳記值是64位值,其中:前32位是一個time_t值(自Unix時代以來的秒數),後32位是ordinal給定秒內操做的增量。
在單個mongod實例中,時間戳記值始終是惟一的。
在複製中,操做日誌具備一個ts字段。該字段中的值反映了使用BSON時間戳值的操做時間。
注意時間戳類型只是在MongoDB內部使用。開發過程當中使用的是日期類型。
BSON包括一個特殊類型,表示可能的最大值。shell中沒有這個類型。
BSON包括一個特殊類型,表示可能的最小值。shell中沒有這個類型。
比較不一樣BSON類型的值時,MongoDB使用如下比較順序,從最低到最高:
MinKey(內部類型)、Null、數字(整數,整數,雙精度數,小數)、符號,字符串、Object、數組、BinData、ObjectId、布爾、日期、時間戳、正則表達式、MaxKey(內部類型)
爲了進行比較,MongoDB將這些類型視爲等效的,在進行比較以前,先將數字類型進行轉換。
默認狀況下,MongoDB將字符串轉換成二進制來進行比較。
Collation是3.4版本的新功能,Collation容許用戶爲字符串比較指定特定的語言規則。
Collation具備如下語法:
{ locale: <string>, caseLevel: <boolean>, caseFirst: <string>, strength: <int>, numericOrdering: <boolean>, alternate: <string>, maxVariable: <string>, backwards: <boolean> }
指定排序規則時,該locale字段爲必填字段;全部其餘排序規則字段都是可選的。
用來選擇語言環境,官方提供了全球不少國家的語言,在其中能夠看到中文的選項值爲zh,英文的值爲en。其餘值的選項,以下:
Locale | caseFirst | alternate | normalization | backwards |
---|---|---|---|---|
zh | off | non-ignorable | FALSE | FALSE |
en | off | non-ignorable | FALSE | FALSE |
默認排序規則參數值取決於語言環境。如下默認參數在全部語言環境中都是一致的:
caseLevel : false strength : 3 numericOrdering : false maxVariable : punct
若是沒有爲集合或操做指定排序規則,則MongoDB使用先前版本中使用的簡單二進制比較進行字符串比較。
對於數組,小於比較或升序排序比較的是數組中的最小元素,大於比較或降序排序比較的是數組中的最大元素。
當字段是單元素數組與非數組字段進行比較時,比較的是數組的元素和非數組字段的值。空數組參與比較的話,會將空數組視爲小於null或缺乏此字段。
MongoDB對BSON對象的比較使用如下順序:
在3.0.0版本中進行了更改,將日期對象放在時間戳對象以前排序。
在早期的版本中是將兩種對象放在一塊兒進行比較的。
MongoDB將不存在的字段視爲是空的BSON對象。
例如:{}和{a : null}進行比較,那麼在比較的時候,a字段和空文檔將視爲等價的。
MongoDB按BinData如下順序排序:
上一篇:MongoDB基礎之入門
下一篇: