MongoDB基礎之BSON數據類型

MongoDB基礎之BSON數據類型

本博客參考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中無此類型 最大鍵

1、類型詳解

下面針對一些經常使用的數據類型進行詳細說明。編程

一、數字

32-bit integer(32位整數)

shell中這個類型不可用,由於JavaScript僅支持64位浮點數,因此32位整數會被自動轉換爲爲64位浮點數。數組

64-bit integer(64位整數)

shell中也不支持這個類型,shell中會使用一個特殊的內嵌文檔來顯示64位整數。服務器

Double(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

二、String(字符串)

BSON字符串是UTF-8。一般,在序列化和反序列化BSON時,每種編程語言的驅動程序都會從語言的字符串格式轉換爲UTF-8。能夠輕鬆地將大多數國際字符存儲在BSON字符串中。此外,MongoDB的$regex查詢在正則表達式字符串中支持UTF-8。

字符串類型可使用sort()方法進行排序,可是sort()是由C++的strcmpAPI實現的,排序可能會錯誤的處理某些字符。

三、Array(數組)

數組是一組值,既能夠既能夠偶組爲有序對象來操做,也能夠做爲無序對象操做。

數組能夠包含不一樣數據類型的元素,實際上,常規鍵值對支持的值均可以做爲數組的元素,甚至是套嵌數組。

文檔中的數組有個特性,就是MongoDB能理解其結構,並指導如何深刻數組內部對其內容進行操做。這樣就能用內容對數組進行查詢和構建索引了。

MongoDB可使用原子更新修改數組中的內容。

值的集合或者列表能夠表示成數組。

{ 「x」 : [「a」, 「b」, 「c」]}

四、Binary data(二進制數據)

二進制數據能夠由任意字節的串組成。不過shell中沒法使用。

五、Undefined(未定義)

文檔中也可使用未定義類型undefined。4.2版本中已經顯示過期。

{ 「x」 : unddefined }

六、ObjectId

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有如下兩個優勢:

  • 1.在MongoDB shell中可使用該ObjectId.getTimestamp()方法訪問建立時間。
  • 2._id存儲的ObjectId值的排序大體是按建立時間排序的。
> ObjectId("5b4c65a07a88f6e8893b70ef").getTimestamp()
ISODate("2018-07-16T09:30:08Z")

MongoDB中存儲的文檔必須有一個「_id」鍵,這個鍵能夠是任何類型的,默認是ObjectId對象。在一個集合中,每一個文檔都有惟一的「_id」值,來確保集合裏面每一個文檔都能被惟一標識。此惟一是在一個集合中保證全局惟一的。

ObjectId是「_id」的默認類型。它設計成輕量型,不一樣的機器都能用全局惟一的同種方法方便地生成它。這是MongoDB採用這種類型的主要緣由。

若是插入文檔的時候沒有「_id」鍵,系統會自動建立一個。這件事能夠由MongoDB服務器來作,也能夠在客戶端由驅動程序完成。

一般會將自動生成_id放在客戶端讓驅動程序來完成,理由以下:

  • 1.ObjectId的生成是有開銷的,在客戶端生成能夠減小數據庫擴展的負擔。
  • 2.在客戶端生成ObjectId,驅動程序可以提供更加豐富的API。

七、Boolean(布爾)

布爾類型有兩個值true和false。

{ 「x」 : true }

八、Date(日期)

日期類型存儲的是從標準紀元開始的毫秒數,不存儲時區。

{「x」 : new Date() }

日期類型存儲的日期大概爲2.9億年。毫秒數爲負值,表示1970年以前的日期。

在JavaScript中,Date對象用作MongoDB的日期類型,建立一個新的Date對象時,調用new Date()而不是Date()。調用Date()實際上會返回對日期的字符串表示,而不是真正的Date對象。這不是MongoDB的特性,而是JavaScript自己的特性。

若是使用錯誤,就會致使日期和字符串混淆,字符串和日期不能互相匹配,最終會給刪除、更新、查詢等不少操做帶來問題。

shell中的日期顯示時使用本地時區設置。日期在數據中是以標準紀元開水的毫秒數的形式存儲的,沒有與之相關的時區信息。

九、Null

null用於表示空值或者不存在的字段。

{「x」 : null }

十、Regular Expression(正則表達式)

文檔中能夠包含正則表達式,採用JavaScript的正則表達式語法。

{ 「x」 : /foobar/i }

十一、JavaScript代碼

文檔中還能夠包含JavaScript代碼。

{「x」: function() { /*…*/} }

十二、Symbol(符號)

shell不支持這種類型。shell將數據庫裏的符號類型轉換成字符串。如今已通過時。

1三、Timestamp(時間戳)

BSON有一個MongoDB內部使用的特殊的時間戳類型,和常的日期類型沒有關係。

時間戳記值是64位值,其中:前32位是一個time_t值(自Unix時代以來的秒數),後32位是ordinal給定秒內操做的增量。

在單個mongod實例中,時間戳記值始終是惟一的。

在複製中,操做日誌具備一個ts字段。該字段中的值反映了使用BSON時間戳值的操做時間。

注意時間戳類型只是在MongoDB內部使用。開發過程當中使用的是日期類型。

1四、Max key(最大值)

BSON包括一個特殊類型,表示可能的最大值。shell中沒有這個類型。

1五、Min key(最小值)

BSON包括一個特殊類型,表示可能的最小值。shell中沒有這個類型。

2、類型之間的比較和排序

比較不一樣BSON類型的值時,MongoDB使用如下比較順序,從最低到最高:

MinKey(內部類型)、Null、數字(整數,整數,雙精度數,小數)、符號,字符串、Object、數組、BinData、ObjectId、布爾、日期、時間戳、正則表達式、MaxKey(內部類型)

一、數值類型

爲了進行比較,MongoDB將這些類型視爲等效的,在進行比較以前,先將數字類型進行轉換。

二、字符串

二進制比較法

默認狀況下,MongoDB將字符串轉換成二進制來進行比較。

Collation

Collation是3.4版本的新功能,Collation容許用戶爲字符串比較指定特定的語言規則。

Collation具備如下語法:

{
   locale: <string>,
   caseLevel: <boolean>,
   caseFirst: <string>,
   strength: <int>,
   numericOrdering: <boolean>,
   alternate: <string>,
   maxVariable: <string>,
   backwards: <boolean>
}

指定排序規則時,該locale字段爲必填字段;全部其餘排序規則字段都是可選的。

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使用先前版本中使用的簡單二進制比較進行字符串比較。

三、Arrays

對於數組,小於比較或升序排序比較的是數組中的最小元素,大於比較或降序排序比較的是數組中的最大元素。

當字段是單元素數組與非數組字段進行比較時,比較的是數組的元素和非數組字段的值。空數組參與比較的話,會將空數組視爲小於null或缺乏此字段。

四、Objects

MongoDB對BSON對象的比較使用如下順序:

  • 1.按照鍵值對在BSON對象中出現的順序遞歸比較它們。
  • 2.比較關鍵字段名稱。
  • 3.若是關鍵字段名稱相等,則比較字段值。
  • 4.若是字段值相等,則比較下一個鍵/值對(返回步驟1)。沒有下一個字段的對象小於有下一個字段的對象。

五、日期和時間戳

在3.0.0版本中進行了更改,將日期對象放在時間戳對象以前排序。

在早期的版本中是將兩種對象放在一塊兒進行比較的。

六、不存在的字段

MongoDB將不存在的字段視爲是空的BSON對象。

例如:{}和{a : null}進行比較,那麼在比較的時候,a字段和空文檔將視爲等價的。

七、BinData

MongoDB按BinData如下順序排序:

  • 首先,比較數據的長度或大小。
  • 而後,按BSON的一字節子類型進行比較。
  • 最後,根據數據執行逐字節比較。

上一篇:MongoDB基礎之入門

下一篇:

相關文章
相關標籤/搜索