mongoDB-document

MongoDB 將數(shù)據(jù)記錄存儲(chǔ)為 BSON類型的 文檔(document)魁蒜。 BSON 是一種二進(jìn)制數(shù)據(jù)類型,是json 的一種擴(kuò)展, bson 支持了更多的數(shù)據(jù)類型俄认。 下圖就是一個(gè)document(文檔) 示例:


document

1. 數(shù)據(jù)結(jié)構(gòu)

document 的數(shù)據(jù)結(jié)構(gòu)如下所示:由若干個(gè)字段-值對(duì)組成,其中字段的值可以是任何 BSON 數(shù)據(jù)類型洪乍,包括嵌入式數(shù)據(jù)結(jié)構(gòu)如 其他文檔眯杏、數(shù)組和文檔數(shù)組等。

{
   field1: value1,
   field2: value2,
   field3: value3,
   ...
   fieldN: valueN 
}

如下申明了一個(gè)mydoc 的文檔壳澳,

var mydoc = {
               _id: ObjectId("5099803df3f4948bd2f98391"),
               name: { first: "Alan", last: "Turing" },
               birth: new Date('Jun 23, 1912'),
               death: new Date('Jun 07, 1954'),
               contribs: [ "Turing machine", "Turing test", "Turingery" ],
               views : NumberLong(1250000)
            }

2. 字段命名

字段(field)的命名都是由字符串組成
字段名稱有以下幾條限制:

  • 字段名 _id 用作主鍵岂贩;它的值在集合中必須是唯一的,是不可變的巷波,可以是數(shù)組以外的任何類型萎津。如果 _id 包含子字段,則子字段名稱不能以 $ 符號(hào)開(kāi)頭
  • 字段名稱不能包含空字符
  • 服務(wù)器允許存儲(chǔ)包含點(diǎn) . 和美元符號(hào) $ 開(kāi)頭的字段名稱
  • MongodB 5.0 增加了對(duì)在字段名稱中使用 $. 的改進(jìn)支持抹镊。但有一些限制锉屈,具體如下:
    在大多數(shù)情況下,無(wú)法直接訪問(wèn)使用此類字段名稱存儲(chǔ)的數(shù)據(jù)髓考。您需要在訪問(wèn)這些字段的查詢中使用 $getField部念、$setField$literal 等輔助方法

對(duì)于不同的字段類型的存儲(chǔ)操作,字段名稱驗(yàn)證規(guī)則并不相同。下面總結(jié)了不同的插入和更新操作如何處理以美元 ($) 為前綴的字段名稱

  • MongoDB 不支持重復(fù)的字段名稱
2.1 插入操作
  • 允許以$ 為前綴的字段作為插入的外層和嵌套字段名稱
// 示例 $price為外層字段
db.sales.insertOne( {
   "$price": 50.00,
   "quantity": 30
} )
  • 使用其他保留關(guān)鍵字的插入允許使用$ 作為前綴儡炼。像 $inc 這樣的運(yùn)算符名稱可以用作字段名稱妓湘,也可以用作 id、db 和 ref 等保留關(guān)鍵字
db.books.insertOne( {
   "$id": "h1961-01",
   "location": {
      "$db": "novels",
      "$ref": "2007042768",
      "$inc": true
} } )
  • 在upset操作中 乌询,如果更新未找到執(zhí)行插入操作時(shí)榜贴, upset 可以接受$ 為前綴的字段, 但是如果更新的匹配到了文檔,此時(shí)妹田,更新操作可能會(huì)導(dǎo)致錯(cuò)誤唬党。 如下例子所示,$hotel 字段以$開(kāi)頭鬼佣, 如果未匹配到date 為"2021-07-07" 的文檔驶拱,此時(shí)支持插入新的文檔, 但是如果匹配到了晶衷,此時(shí)更新操作失敗
db.expenses.updateOne(
   { "date": "2021-07-07" },
   { $set: {
      "phone": 25.17,
      "$hotel": 320.10
   } },
   { upsert: true }
)
2.2 更新操作
  • 文檔替代更新
    文檔的更新要么新字段替換現(xiàn)有字段蓝纲,要么修改這些字段。在更新執(zhí)行替換的情況下晌纫,不允許以美元$ 為前綴的字段作為最外層字段名稱税迷。
    例如: 有如下的文檔,$rooms 字段是最外層字段,此時(shí)不允許對(duì)該字段的修改(不包括包括子文檔锹漱,子文檔中的字段可以箭养,例如brbath),但是可以對(duì)其他非$前綴的字段修改哥牍,如address 字段毕泌,包括address 字段中的子字段$number$street 修改
{
   "_id": "E123",
   "address": {
      "$number": 123,
      "$street": "Elm Road"
   },
   "$rooms": {
      "br": 2,
      "bath": 1
   }
}
// 可以
db.expenses.updateOne(
   { "_id": "E123" },
   { $set: { "address.$street": "Elm Ave" } }
)

// 可以
db.expenses.updateOne(
   { "_id": "E123" },
   { $set: { "$rooms.br": "3222" } }
)
// 更新報(bào)錯(cuò)
db.expenses.updateOne( 
  { "_id": "E123" },
   { $set: { "$rooms":{"bath":22,"bath":1111}}}
)

  • 文檔的修改更新
    當(dāng)更新修改而不是替換現(xiàn)有文檔字段時(shí),以$ 為前綴的字段可以是最外層字段名稱砂心⌒复剩可以直接訪問(wèn)子字段,但您需要一個(gè)輔助方法來(lái)訪問(wèn)最外層字段
// 示例文檔
{
   _id: ObjectId("610023ad7d58ecda39b8d161"),
   "part": "AB305",
   "$bin": 200,
   "quantity": 100,
   "pricing": { sale: true, "$discount": 60 }
}

修改非$前綴的字段

db.inventory.findAndModify( {
    query: { "part": { $eq: "AB305" } },
    update: { $inc: { "pricing.$discount": 10 } }
} )

修改非$前綴的最外層字段,通過(guò)getField 和literal 實(shí)現(xiàn)

db.inventory.findAndModify( {
   query: { $expr: {
      $eq: [ { $getField: { $literal: "$bin" } }, 200 ]
   } },
   update: { $inc: { "quantity": 10 } }
} )
  • 文檔的聚合修改
    $replaceWith$setField辩诞、$getField$literal 聯(lián)合使用來(lái)修改聚合管道中的$ 前綴字段
// 示例文檔
{
   "_id": 100001,
   "$term": "fall",
   "registered": true,
   "grade": 4
}

使用管道創(chuàng)建一個(gè)名為spring2022的新集合坎弯,更新$ 為前綴的 $term字段

db.school.aggregate( [
   { $match: { "registered": true } },
   { $replaceWith: {
      $setField: {
         field: { $literal: "$term" },
         input: "$$ROOT",
         value: "spring"
   } } },
   { $out: "spring2022" }
] )

3. 點(diǎn)符號(hào)

MongoDB 使用點(diǎn)符號(hào)來(lái)訪問(wèn)數(shù)組的元素和訪問(wèn)嵌入文檔的字段

3.1 數(shù)組

要通過(guò)從零開(kāi)始的索引位置指定或訪問(wèn)數(shù)組的元素,請(qǐng)將數(shù)組名稱與點(diǎn) (.) 和從零開(kāi)始的索引位置連接起來(lái)译暂,并用引號(hào)引起來(lái)

"<array>.<index>"

示例:

{
   ...
   contribs: [ "Turing machine", "Turing test", "Turingery" ],
   ...
}
3.2 嵌入式文檔

要使用點(diǎn)表示法指定或訪問(wèn)嵌入文檔的字段抠忘,請(qǐng)將嵌入文檔名稱與點(diǎn) (.) 和字段名稱連接起來(lái),并用引號(hào)引起來(lái)

"<embedded document>.<field>"

示例:

{
   ...
   name: { first: "Alan", last: "Turing" },
   contact: { phone: { type: "cell", number: "111-222-3333" } },
   ...
}
  • "name.last": 獲取name 字段中嵌入的子字段
  • "contact.phone.number": 獲取contact 嵌入文檔中phone 中的子字段 number

4. 文檔限制

4.1 文檔大小

BSON 文檔的最大大小為 16 兆字節(jié)
最大文檔大小有助于確保單個(gè)文檔不會(huì)使用過(guò)多的 RAM外永,或者在傳輸期間不會(huì)使用過(guò)多的帶寬崎脉。為了存儲(chǔ)大于最大大小的文檔,MongoDB 提供了 GridFS API伯顶。

4.2 文檔字段有序性

與 JavaScript 對(duì)象不同囚灼,BSON 文檔中的字段是有序的

查詢操作時(shí)字段順序:

  • 比較文檔時(shí)骆膝,字段排序很重要 例如 {a: 1, b: 1} 與 {b: 1, a: 1} 是不同的
  • 為了高效的查詢執(zhí)行,查詢引擎可以在查詢處理期間重新排序字段灶体。在其他情況下阅签,處理下列運(yùn)算符時(shí)可能會(huì)發(fā)生重新排序字段:$project$addFields蝎抽、$set$unset政钟。
    1. 字段重新排序可能發(fā)生在中間結(jié)果以及查詢返回的最終結(jié)果中
    2. 由于某些操作可能會(huì)重新排序字段,因此不應(yīng)依賴使用前面列出的運(yùn)算符的查詢返回的結(jié)果中的特定字段排序樟结。

寫(xiě)操作時(shí)字段順序
對(duì)于寫(xiě)入操作养交,MongoDB 保留文檔字段的順序,但以下情況除外:

  • _id 字段始終是文檔中的第一個(gè)字段
  • 對(duì)字段的重新命名的更新操作($rename)可能會(huì)導(dǎo)致文檔中的字段重新排序
4.3 _id字段

在 MongoDB 中瓢宦,存儲(chǔ)在集合中的每個(gè)文檔都需要一個(gè)唯一的 _id 字段作為主鍵碎连。如果插入的文檔省略了 _id 字段,MongoDB 驅(qū)動(dòng)程序會(huì)自動(dòng)為 _id 字段生成一個(gè) ObjectId刁笙。 這也適用于通過(guò)帶有 upsert: true 的更新操作插入的文檔

_id 字段具有以下限制:

  • 默認(rèn)情況下破花,MongoDB 在創(chuàng)建集合期間會(huì)在 _id 字段上創(chuàng)建唯一索引
  • _id 字段始終是文檔中的第一個(gè)字段。如果服務(wù)器先接收到一個(gè)沒(méi)有_id字段的文檔疲吸,那么服務(wù)器會(huì)自動(dòng)生成該字段并將該字段移到開(kāi)頭
  • 如果 _id 包含子字段,則子字段名稱不能開(kāi)頭 帶有 ($) 符號(hào)
  • _id 字段可以包含任何 BSON 數(shù)據(jù)類型的值前鹅,除了數(shù)組摘悴、正則表達(dá)式和未定義類型

_id 字段常用值:

  • 使用ObjectId 類型
  • 使用自然唯一標(biāo)識(shí)符。這節(jié)省了空間并避免了額外的索引
  • 生成一個(gè)自動(dòng)遞增的數(shù)字
  • 在您應(yīng)用程序代碼中生成一個(gè) UUID舰绘, 并將UUID以BinData 類型存儲(chǔ)蹂喻。 使得在集合和 _id 索引中更有效地存儲(chǔ) UUID 值
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市捂寿,隨后出現(xiàn)的幾起案子口四,更是在濱河造成了極大的恐慌,老刑警劉巖秦陋,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蔓彩,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡驳概,警方通過(guò)查閱死者的電腦和手機(jī)赤嚼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)顺又,“玉大人更卒,你說(shuō)我怎么就攤上這事≈烧眨” “怎么了蹂空?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵俯萌,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我上枕,道長(zhǎng)咐熙,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任姿骏,我火速辦了婚禮糖声,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘分瘦。我一直安慰自己蘸泻,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布嘲玫。 她就那樣靜靜地躺著悦施,像睡著了一般。 火紅的嫁衣襯著肌膚如雪去团。 梳的紋絲不亂的頭發(fā)上抡诞,一...
    開(kāi)封第一講書(shū)人閱讀 51,624評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音土陪,去河邊找鬼昼汗。 笑死,一個(gè)胖子當(dāng)著我的面吹牛鬼雀,可吹牛的內(nèi)容都是我干的顷窒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼源哩,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼鞋吉!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起励烦,我...
    開(kāi)封第一講書(shū)人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤谓着,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后坛掠,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體赊锚,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年却音,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了改抡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡系瓢,死狀恐怖阿纤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情夷陋,我是刑警寧澤欠拾,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布胰锌,位于F島的核電站,受9級(jí)特大地震影響藐窄,放射性物質(zhì)發(fā)生泄漏资昧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一荆忍、第九天 我趴在偏房一處隱蔽的房頂上張望格带。 院中可真熱鬧,春花似錦刹枉、人聲如沸叽唱。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)棺亭。三九已至,卻和暖如春蟋软,著一層夾襖步出監(jiān)牢的瞬間镶摘,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工岳守, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留凄敢,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓湿痢,卻偏偏與公主長(zhǎng)得像贡未,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蒙袍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容