MongoDB的文檔類似于JSON甚颂,而JSON只有6種數(shù)據(jù)類型蜜猾。
分別是:null,布爾振诬,數(shù)字蹭睡,字符串,數(shù)組赶么,對象肩豁。
以上6中類型可以表示絕大多數(shù)的數(shù)據(jù)了,但是仍然有一些數(shù)據(jù)需要其他類型辫呻。
比如清钥,JSON沒有日期類型,只有一種數(shù)字類型放闺,無法區(qū)分整數(shù)和浮點數(shù)祟昭,更不用說32位還是64的數(shù)字的。
MongoDB的設(shè)計者考慮的很充分怖侦,在JSON基礎(chǔ)之上篡悟,又添加了很多類型,使之可以保存幾乎所有的數(shù)據(jù)類型础钠。
- null:用于表示空值,或者不存在的字段
{ "x" : null} - 布爾:布爾類型有兩個值叉谜,'true' 和 'false'
{ "x" : true } - 32位整數(shù):shell中不支持旗吁,JS僅支持64位浮點數(shù),所以32位整數(shù)會被自動轉(zhuǎn)換停局。
- 64位整數(shù):shell中同樣不支持很钓,shell會視同特殊的內(nèi)嵌文檔來表示64位整數(shù)香府。
- 64位浮點數(shù):shell中的數(shù)字都是這個類型。
{ "x" : 3.14} { "x" : 3 } //3在這里也是一個浮點數(shù) - 字符串:UTF-8字符串
{ "x" : "this is a string"} - 符號:shell不支持這種類型码倦,shell會將數(shù)據(jù)庫里的符號轉(zhuǎn)換位字符串
- 對象id:是文檔的12字節(jié)的唯一ID企孩。
{ "x" : ObjectId() } - 日期:從標(biāo)準(zhǔn)紀(jì)元開始的毫秒數(shù)。
{ "x" : new Date() } - 正則表達(dá)式:文檔中可以包含正則表達(dá)式袁稽,采用JS正則語法勿璃。
{ "x" : "/foobar/i" } - 代碼:文檔中還能包含JS代碼。
{ "x" : function() { ... } } - 二進(jìn)制數(shù)據(jù):可由任意字節(jié)組成推汽,shell中無法使用补疑。
- 最大值,最小值:BSON中表示歹撒,shell中無法使用莲组。
- 未定義:未定義類型,undefined
{ "x" : undefined } - 數(shù)組:值得集合或者列表暖夭。
{ "x" : [ "a", "b", "c"] } - 內(nèi)嵌文檔:就是文檔的值又是一個文檔锹杈。
{ "x" : { "y" : "abc" } }
以下是這些類型要注意的地方
數(shù)字問題
JS中只有一種數(shù)值類型,64位浮點數(shù)迈着,而在MongoDB中有3種數(shù)據(jù)類型竭望,32位整數(shù),64位整數(shù)寥假,64位浮點數(shù)市框。
默認(rèn)情況下,shell中的 數(shù)值都被MongoDB當(dāng)做64位浮點數(shù)處理糕韧。
這意味著枫振,你從MongoDB中獲取了一個32位整數(shù),修改文檔之后萤彩,將文檔存回去的時候粪滤,這個32位整數(shù)就會被轉(zhuǎn)換成64位浮點數(shù),即便保持這個整數(shù)原封不動也會是這樣雀扶。
所以杖小,明智的做法是,盡量不要在shell下覆蓋整個文檔愚墓。
日期問題
MongoDB中使用Date對象作為日期類型予权。
創(chuàng)建一個日期對象,會用new Date()浪册。如果調(diào)用構(gòu)造函數(shù)(Date()扫腺,前面沒有new關(guān)鍵字),則會生成一個時間的字符串村象,并非真正的日期類型笆环,這樣會導(dǎo)致日期和字符串混淆攒至。因為日期和字符串是不能互相匹配的,這將會給數(shù)據(jù)庫的操作帶來很大麻煩躁劣。
shell中的日期迫吐,使用本地時區(qū)設(shè)置,但是日期在數(shù)據(jù)庫中存儲的是從標(biāo)準(zhǔn)紀(jì)元開始的毫秒數(shù)账忘,沒有時區(qū)的相關(guān)信息志膀,可以用一個字段來單獨保存時區(qū)信息。
數(shù)組
既可以作為有序?qū)ο髞聿僮鳎愃屏斜砩撂眩瑮N嗳矗犃校部梢韵駸o序?qū)ο髞聿僮鳎愃萍希?br>
數(shù)組可以包含不同數(shù)據(jù)類型的元素败去。
如果經(jīng)常查詢某個數(shù)組中的元素放航,可以對其創(chuàng)建索引,來提高性能圆裕。(以后要重點看這個)
_id和OjbectId
MongoDB中存儲的文檔必須有一個_id字段广鳍,它是在插入數(shù)據(jù)時系統(tǒng)自動添加的,這是一個OjbectId類型的數(shù)據(jù)吓妆,用來確保集合中每個文檔都是唯一的赊时。(注意是區(qū)分同一個集合中的文檔,不同集合的文檔的_id值可以一樣)行拢。
OjbectId使用12字節(jié)的存儲空間祖秒,每個字節(jié)是兩位16進(jìn)制數(shù)字,是一個24位的字符串舟奠。
上圖每個黑色的方塊表示1個字節(jié)竭缝,分別從1-12編號。
1-4表示:時間戳沼瘫,單位是秒抬纸。
5-7表示:主機(jī)的唯一標(biāo)識符。
8-9表示:PID耿戚,進(jìn)程標(biāo)識符湿故。
10-12表示:自增的計數(shù)器。
看到這里也許就明白了膜蛔,前9位數(shù)就保證了坛猪,同一秒鐘不同機(jī)器不同進(jìn)程產(chǎn)生的OjbectId是唯一的。
同一秒最多可以產(chǎn)生:2的8次方 的3次方個_id皂股,16777216個墅茉。
如果插入數(shù)據(jù)時沒有_id,系統(tǒng)會幫你創(chuàng)建一個_id鍵,但是通常都在客戶端完成這件事躁锁,因為這樣可以降低服務(wù)器的壓力,而且擴(kuò)展應(yīng)用層比擴(kuò)展數(shù)據(jù)層方便的多卵史。而且在客戶端生成_id战转,驅(qū)動程序會提供更豐富的API。