MongoDB的設(shè)計(jì)模式策略
MongoDB是一項(xiàng)通用工具,但它也并非***。針對(duì)某些MongoDB不適用的場(chǎng)合,有時(shí)可選用設(shè)計(jì)模式來(lái)加以應(yīng)對(duì)。
MongoDB是一個(gè)NoSQL文檔數(shù)據(jù)庫(kù),在大多數(shù)情況下是一個(gè)相對(duì)理想的選擇,即使是在其不適用的情況下,也仍然可以依靠下面所列舉的這些設(shè)計(jì)模式來(lái)克服其局限性。
本文將針對(duì)我的另一篇文章《MongoDB的好壞惡》( MongoDB : The Good, The Bad, and the Ugly)中所提及的一些局限性,提供一個(gè)相對(duì)應(yīng)的解決方案。
1. 查詢(xún)命令分離模式
在副本集中職責(zé)被分離到不同的節(jié)點(diǎn)。最基本的***類(lèi)節(jié)點(diǎn)可能也同時(shí)占據(jù)著首要地位,它只需要儲(chǔ)存那些寫(xiě)入和更新所需的數(shù)據(jù)。而查詢(xún)工作則交由第二類(lèi)節(jié)點(diǎn)來(lái)執(zhí)行。這一模式將提升首要節(jié)點(diǎn)服務(wù)器的寫(xiě)吞吐量,因?yàn)楫?dāng)寫(xiě)入一組對(duì)象時(shí),需要更新及插入的數(shù)據(jù)量也隨之減少,除此之外,二類(lèi)節(jié)點(diǎn)也得益于較少的待更新數(shù)據(jù)和其自身所具有的為其工作量而優(yōu)化的內(nèi)存工作集。
2. 應(yīng)用程序級(jí)事務(wù)模式
MongoDB不支持事務(wù)和文件內(nèi)部鎖定。然而,依據(jù)應(yīng)用邏輯,應(yīng)當(dāng)保留queue用法。
- db.queue.insert( { _id : 123,
- message : { },
- locked : false,
- tlocked : ISODate(),
- try : 0 });
- var timerange = date.Now() - TIMECONSTANT;
- var doc = db.queue.findAndModify( { $or : [ { locked : false }, { locked : true, tlocked : {
- $lt : timerange } } ], { $set : { locked : true, tlocked : date.Now(), $inc : { try : 1 } } }
- );
- //do some processing
- db.queue.update( { _id : 123, try : doc.try }, { } );
3. Bucketing模式
當(dāng)文本含有一個(gè)不斷增長(zhǎng)的數(shù)組時(shí),則使用Bucketing模式,例如指令。而指令線(xiàn)可能會(huì)擴(kuò)展到超過(guò)文檔大小的合理值。該模式經(jīng)由編程方式處理,并通過(guò)公差計(jì)算觸發(fā)。
- var TOLERANCE = 100;
- for( recipient in msg.to) {
- db.inbox.update( {
- owner: msg.to[recipient], count: { $lt : TOLERANCE }, time : { $lt : Date.now() } },
- { $setOnInsert : { owner: msg.to[recipient], time : Date.now() },
- { $push: { "messages": msg }, $inc : { count : 1 } },
- { upsert: true } );
4. 關(guān)系模式
有時(shí),會(huì)有不能插入整個(gè)文檔的情況,例如人體建模時(shí),我們就可以使用該模式來(lái)建立關(guān)系。
- 確定數(shù)據(jù)是否屬于該文檔,即二者間是否有關(guān)系。
- 如果可能的話(huà),特別是面對(duì)有用的獨(dú)有(專(zhuān)屬)數(shù)據(jù)時(shí),插入文檔。
- 盡可能不參考id值。
- 對(duì)關(guān)系中的有用部分進(jìn)行反規(guī)范化處理。好的候選不會(huì)經(jīng)常甚至從不更改值,并且頗為有用。
- 關(guān)注反規(guī)范數(shù)據(jù)的更新和關(guān)系修復(fù)。
- {
- _id : 1,
- name : ‘Sam Smith’,
- bio : ‘Sam Smith is a nice guy’,
- best_friend : { id : 2, name : ‘Mary Reynolds’ },
- hobbies : [ { id : 100, n :’Computers’ }, { id : 101, n : ‘Music’ } ]
- }
- {
- _id : 2,
- name : ‘Mary Reynolds’
- bio : ‘Mary has composed documents in MongoDB’,
- best_friend : { id : 1, name : ‘Sam Smith’ },
- hobbies : [ { id : 101, n : ‘Music’ } ]
- }
5. 物化路徑模式
在一個(gè)數(shù)據(jù)模型的樹(shù)模式中,同一對(duì)象類(lèi)型是該對(duì)象的子對(duì)象,這種情況下可以使用物化路徑模型來(lái)以獲取更高效的檢索、查詢(xún)。示例如下:
- { _id: "Books", path: null }
- { _id: "Programming", path: ",Books," }
- { _id: "Databases", path: ",Books,Programming," }
- { _id: "Languages", path: ",Books,Programming," }
- { _id: "MongoDB", path: ",Books,Programming,Databases," }
- { _id: "dbm", path: ",Books,Programming,Databases," }
按字段路徑查詢(xún)樹(shù)模式:
- db.collection.find().sort( { path: 1 } )
使用路徑字段的常規(guī)表達(dá)來(lái)找出Programming的后代集:
- db.collection.find( { path: /,Programming,/ } )
在Books是top parent的情況下查詢(xún)Books的后代集:
- db.collection.find( { path: /^,Books,/ } )