04 文件設計基礎
← 03 Payload 與 Process 欄位 | 回到 MongoDB 資料建模設計 | 下一篇 → 05 索引與優化
這一段是整場的方法論核心:MongoDB 的 schema 要怎麼想,以及「link 還是 embed」的決策準則。
Schema Design in MongoDB(p.23)
Schema is defined at the application-level —— schema 定義在應用層,不是資料庫層。
- Focus on the needs of the application —— 聚焦在應用的需求。
- Not the abstract nature of the data —— 不是聚焦在資料本身的抽象結構。
- Design is the part of each phase in its lifetime —— 設計貫穿應用的整個生命週期,不是一次定案。
- 一句話總結:Schema design should focus on the application and not the data。
講師展開:schema design 是「持續」的,不是一次性
- 傳統關聯式的直覺是「一開始就定好 schema」。但 MongoDB 的一大優勢是靈活性(彈性):不需要在設計初期就把 schema 完全定死。
- MongoDB 的 schema 本質上是「一份 JSON / 一個 document」,之後可以在應用的生命週期裡:
- 增加欄位、調整欄位,成本非常低;
- 隨業務演進逐步擴展。
- 所以 schema design 不是某個時間點的動作,而是存在於應用整個生命週期裡。哪裡最能貼近需求、最快回應需求變化,就在哪裡調整。
- 出發點永遠是 application 的需求(
mile需求導向),而不是反過來從資料的抽象結構去推。目的是為資料找一個「榮譽存放處」——恰當地服務應用怎麼用它。
Three Considerations(p.24)—— 三大考量
分析需求時,圍繞三件事:
- The data the application needs —— 應用需要哪些資料。
- Application’s read usage of the data —— 應用怎麼讀這份資料。
- Application’s write usage of the data —— 應用怎麼寫這份資料。
講師的做法:在需求分析階段,先把「應用需要什麼資料、讀操作長什麼樣、寫操作長什麼樣」管理清楚,確立實體、實體之間的關係,再看哪些關係該合併(embed)、哪些該分開(link)。
- 讀寫的權衡:要什麼樣的資料、要什麼樣的讀?→ 決定資料怎麼擺、要不要為讀去設冗餘(denormalize)。
- 寫的形態:是簡單寫一張 document,還是要跨多個 document?
- 根據讀寫的相對頻率與形態,決定合併或拆開、以及索引怎麼設(→ 05 索引與優化)。
Document Design Basics(p.25)—— Link 還是 Embed?
決定兩個實體之間要 Link(存參照)還是 Embed(內嵌),問自己五個問題:
- Do I want the embedded info a lot of the time? —— 這份資料是不是「經常要一起被讀出來」?經常要 → 傾向 embed。
- Do I need to search with the embedded info? —— 需不需要「用這份內嵌資料去搜尋(當查詢條件)」?
- Does the Embedded info change often? —— 這份資料是否經常變動?經常變動且被很多地方冗餘 → 傾向 link(否則每次變動要改很多地方)。
- Do I need the latest version or the same version? —— 你要的是最新版,還是當時那一版?(呼應 06 設計模式 Design Patterns 的 Versioning。)
- Is the embedded info shared – really? —— 這份資料真的被共享嗎?如果只是看起來被共享、其實各自獨立,那 embed 反而簡單。
講師的判準口訣
- 經常要被一起讀出的 → 盡量 embed(一次查詢就拿到,速度快)。
- 經常需要獨立搜尋 / 經常變動 / 真正被大量共享的 → 傾向 link(避免冗餘資料到處要維護、避免更新一個地方要改很多份)。
- embed 的代價是「勇於冗餘」:把一些外部欄位複製進主 document,讓查詢時不必再往外抓——值不值得,看讀取頻率與變動頻率的取捨。
範例思考:Invoice Address,link 還是 embed?(投影片留的問題)
What about an Invoice Address, link, or embed?
講師的推導:
- 訂單/發票(invoice)裡的收件地址,該 embed 還是 link 到客戶(customer)的地址?
- 關鍵在需求:開發票、看發票時,是否需要「那張發票當下的地址」?
- 如果需求是「查訂單時要看到當時出貨的地址」→ 應該把地址 embed 進 invoice。因為客戶地址之後可能會變,但這張發票要保留的是開立當時的地址(同 06 設計模式 Design Patterns Versioning 的「當時版本 vs 最新版本」)。
- 如果不需要看地址、或只要最新地址 → 可以只在 invoice 存一個發票 ID / 客戶參照,需要時再去 customer 撈(link)。
- 結論回到需求:先問「你的應用需求是什麼」,再決定用哪種存法——順著需求去設計資料結構,而不是反過來讓資料決定需求。
小結
- schema 定在應用層,focus on application not data;設計貫穿整個生命週期,可持續演進。
- 三大考量:要哪些資料、怎麼讀、怎麼寫。
- link vs embed 的五問:常一起讀?要拿來搜?常變動?要最新還當時?真的共享?
- 大原則:能 embed(常一起讀)就 embed;要獨立查/常變/真共享就 link。
→ 下一篇:05 索引與優化