溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

利用聚合概念指導(dǎo)MongoDB的Schema設(shè)計是怎么樣的

發(fā)布時間:2021-11-03 10:35:26 來源:億速云 閱讀:243 作者:柒染 欄目:大數(shù)據(jù)

這期內(nèi)容當(dāng)中小編將會給大家?guī)碛嘘P(guān)利用聚合概念指導(dǎo)MongoDB的Schema設(shè)計是怎么樣的,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

習(xí)慣的力量強大卻往往無法察覺。往往不經(jīng)意之間,陷入習(xí)慣的陷阱中卻不自知。

在我們的項目中,為了能夠保存分析報表以及用戶設(shè)置的報表查詢條件,我們將這些信息視為報表元數(shù)據(jù)存儲在MongoDB中。要存儲的元數(shù)據(jù)包括:

  • 報表分類(ReportCategory)

  • 報表(Report)

  • 報表查詢條件(QeuryCondition)

一個報表分類會包含多個報表,同一個報表只能屬于一個分類。每個報表提供了多個標(biāo)準(zhǔn)查詢條件和多個用戶自定義查詢條件。

利用聚合概念指導(dǎo)MongoDB的Schema設(shè)計是怎么樣的

我需要為這些元數(shù)據(jù)設(shè)計MongoDB的DB  Schema。最初考慮將這三個概念合起來定義為元數(shù)據(jù)表的一條記錄。之后想到對于一個報表而言,需要頻繁對報表的查詢條件進行增刪操作,似乎又應(yīng)該將查詢條件單獨分離出來。那么報表分類與報表呢?是否將報表也獨立出來才合適?對于MongoDB這樣的Document數(shù)據(jù)庫而言,將Report作為ReportCategory的embedded屬性也是可行的,至少不會像關(guān)系型數(shù)據(jù)庫那樣會產(chǎn)生數(shù)據(jù)冗余。倘若要分開,當(dāng)需要查詢某個分類下的所有報表時,還得多余地做一次Link。

好糾結(jié)啊!似乎怎么設(shè)計都是可行的,又仿佛總有不如意處。

正在思索中,突然想起對于這樣面向文檔的NoSQL數(shù)據(jù)庫而言,使用聚合(Aggregate)來觀察表記錄會更加恰當(dāng)。這個想法恍若閃電般迅捷而銳利,猛地撞向腦中的思緒,一下子點燃了我的設(shè)計思維。

這里所謂“聚合”,非面向?qū)ο笾斜磉_對象關(guān)系的概念,而是領(lǐng)域驅(qū)動設(shè)計(DDD)對對象邊界的思考。關(guān)于聚合(Aggregate)的設(shè)計,我根據(jù)過往的經(jīng)驗,整理出五條設(shè)計原則:

  • 聚合作為一種邊界,主要用于維護業(yè)務(wù)完整性,此時應(yīng)遵循業(yè)務(wù)規(guī)則中定義的不變量(Invariant)

  • 作為聚合邊界內(nèi)的非聚合根實體對象,若可能被別的調(diào)用者單獨調(diào)用,則應(yīng)該作為單獨的聚合分離出來

  • 在聚合邊界內(nèi)的非聚合根對象,與聚合根之間應(yīng)該存在直接或間接的引用關(guān)系,且可以通過對象的引用方式;若必須采用Id來引用,則說明被引用的對象不屬于該聚合

  • 若一個對象缺少另一個對象作為其主對象就不可能存在,則該對象一定屬于該主對象的聚合邊界內(nèi)

  • 若一個實體對象,可能被多個聚合引用,則該實體對象應(yīng)首先考慮作為單獨的聚合

這些設(shè)計原則都是我在探索聚合設(shè)計時的一些思考,多次實踐下來,竊以為頗有指導(dǎo)價值。這里不再鋪開,留待以后的文章詳述。單說本例,我們該如何運用這些原則來思考ReportCategory、Report與QueryCondition之間的關(guān)系?

顯然,套用這些原則,我認(rèn)為前面糾纏不清的混亂思路已可迎刃而解。從業(yè)務(wù)完整性看,Report雖屬于ReportCategory,但二者未嘗有強的約束關(guān)系,即不存在業(yè)務(wù)上的不變量(Invariant)。例如ReportCategory可以沒有Report,成為一個空的分類,我們也可以撇開ReportCategory,單獨查詢所有的Report。倘若我們將Report放到ReportCategory聚合中,由于Report可能會被單獨調(diào)用,聚合的邊界保護反而成為了障礙,不合理。

于是,我們可以得出***個結(jié)論:ReportCategory和Report應(yīng)該屬于兩個不同的聚合。

基于第四條原則,我們可以提出問題:當(dāng)QueryCondition缺少Report對象后,還有存在意義嗎?答案一目了然,沒有Report,就沒有QueryCondition。皮之不存毛將焉附!第二個結(jié)論自然得來:Report與QueryCondition應(yīng)屬于同一個聚合。于是,模型呼之欲出:

利用聚合概念指導(dǎo)MongoDB的Schema設(shè)計是怎么樣的

上圖是領(lǐng)域模型而非數(shù)據(jù)模型。站在領(lǐng)域驅(qū)動設(shè)計的角度,這才是正確的打開姿勢。那么,使用該領(lǐng)域模型去指導(dǎo)MongoDB的Schema設(shè)計,是否有將領(lǐng)域混入技術(shù)實現(xiàn)之嫌呢?從設(shè)計方向看,先考慮領(lǐng)域模型才是正解,DB的技術(shù)實現(xiàn)應(yīng)為了滿足該領(lǐng)域模型而設(shè)計。只有當(dāng)領(lǐng)域模型可能阻礙技術(shù)實現(xiàn),又或者依據(jù)領(lǐng)域模型得到的Schema設(shè)計不滿足性能或其他質(zhì)量屬性需求時,才應(yīng)該反過來調(diào)整領(lǐng)域模型。對于MongoDB這種面向Document的數(shù)據(jù)庫,以聚合概念指導(dǎo)Schema設(shè)計,可謂水到渠成,不僅沒有違和之感,反而讓Repository的實現(xiàn)變得更加簡單、自然。

在項目開發(fā)過程中,我先入為主地做了技術(shù)選型,從而習(xí)慣性地開始針對MongoDB進行Schema設(shè)計,反而忘了領(lǐng)域驅(qū)動設(shè)計的指導(dǎo)原則。技術(shù)人員對技術(shù)實現(xiàn)往往見獵心喜,因而忽略了領(lǐng)域設(shè)計的驅(qū)動力,慎之慎之!

上述就是小編為大家分享的利用聚合概念指導(dǎo)MongoDB的Schema設(shè)計是怎么樣的了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI