mongodb 的 schema 設計方法

mongodb 的schema設計方法

前言

mongodb是NoSQL的表明,從使用關係型數據庫(MySQL)到使用非關係型數據庫(mongodb),其中的一些之前的設計的思惟慣性老是在不知不覺的影響着本身的決策。設計的思想有共同之處,也有很大的不一樣。mongodb的優點在於他表示數據的方式很是豐富。下面就來總結一些設計的原則和方法。mongodb

原則

schema的設計最重要的不是當前設計的可擴展性,對設計的可讀性,仍是說原來的設計三範式。最重要的在於,你的app通常展示出來的數據是什麼結構,就設計成什麼樣。取出即用。舉個例子來講,若是設計一個博客的schema,按照原來的方法, 你可能會設計成:數據庫

posts
{
  _id: ,
  title: ,
  body: ,
  author: ,
  date: 
}

comments
{
  _id: ,
  post_id: ,
  author: ,
  order: 
}

tags
{
  _id: ,
  tag: ,
  post_id:
}

可是更好的設計是:json

{
  _id: ,
  author: ,
  body: ,
  comments : [
    {
      body: ,
      email: ,
      author: ,
    },
    ...
    {
     ...
    }
  ],
  date: ,
  tags: [
    ...
  ],
  title: 
}

原來的設計範式的目標

  1. 儘量的減小數據庫數據修改的難度(減小數據冗餘)數組

  2. 最小化數據庫設計擴展的改動app

  3. 避免數據庫訪問時的歧義數據庫設計

在mongodb中:post

  1. 默認的來講設計的時候是要避免數據冗餘的性能

  2. 不存在這樣的問題,由於mongo中的schema很是靈活,你能夠隨時的改動測試

  3. 因爲設計的時候就儘量的按照應用須要的數據的形式設計,取出即用,因此第三個問題出現的機率也比較少設計

沒有約束怎麼辦?

在mongo中,最常常思考的問題就是,沒有外鍵怎麼保持數據一致性?正如上述博客的第一種設計中,你在新插入一個評論的時候,數據庫是不會保證你這個post_id是否是真在在posts這個collection裏面有對應值。

解決的辦法就是像第二種設計中的作法,把他嵌入在posts這個collection.因爲這個時候評論已是post的一部分,就不再用擔憂插入的評論沒有對應到一篇博客的問題。

沒有事務怎麼辦?

在目前,mongodb是不支持事務的。也就是說,若是你一個業務須要修改好幾條記錄,你是沒辦法保證當其中一個操做失敗的之後將其它操做回滾的,這種時候又應該怎麼辦?

雖然mongo沒有提供事務,可是他提供了很是豐富的原子操做,咱們應該充分利用這一點。在關係型數據庫中,你可能有幾張表,而後要經過join的方式去連接。因此你須要事務去同時修改幾張表。可是在mongo中,在設計的時候你已經prejoin了(就是你已經把它們都嵌入在了同一個collection),你只須要直接一次修改整個post就能夠實現事務的效果。

總的來講,解決的辦法有三個:

  1. 重建你的設計,使得你能經過原子操做一次把它們都修改完

  2. 在你的軟件中實現鎖的機制,用尋找和修改寫一系列的測試來實現。

  3. 在大量的數據或者不嚴格的場景中,容忍這種錯誤

典型的設計場景

一對一的關係

好比說應聘者和簡歷的關係。除非嵌在一塊兒會致使你的數據大於16MB(mongo的限制),你都應該嵌在一塊兒。作好的作法就是將一個比較少使用的嵌入一個常常食用的當中。

一對多的關係

好比說城市和人的關係,博客和評論

對於像城市和人的關係這樣的,一個城市實在是對應了太多太多的人。若是將人嵌入在城市中,不太合適。在城市信息嵌入在人中就更不合適了,由於還會產生大量數據冗餘,更新信息也特別麻煩。這種狀況下最好的作法就是分開兩個collection,而後人的collection中每一條都有一個city字段,來對應城市collection中的一條。

若是是像博客和評論這樣一個對應的不是特別多的時候,最好的最法仍是嵌進去

多對多的關係

例如書和做者的關係,老師和學生的對應關係

對於像書和做者這樣,比較少對應比較少的,一個可行的作法就是分開兩個collection。書collection中存一個authors數組,做者 collection中存一個books數組,互相對應。這種作法很差的地方就在與要手動維護數據一致性。另外一個作法就是嵌在一塊兒,這樣會有性能的提高,不過這種作法會致使數據冗餘,看具體的狀況來取捨。特別的像老師和學生這種關係,最好最好就是不要將老師嵌在學生中,由於極可能一個新來的老師就尚未學生,這樣你就沒辦法把這位老師加入到系統中。

樹形結構

一個典型的場景就是像amazon這樣的電商,一個商品分類下可能有不少個子分類。

其中的一個作法就是創建一個分類的collection,而後每一個分類有一個parent_id字段,可是這樣不便於找到他全部的祖先。因此比較好的作法是再加一個ancesters的數組字段,記錄他全部的祖先的id,這樣就能方便的查詢到他的祖先和後代。

嵌入的優點

  • 提升讀的效率。這意味着你要獲取數據只須要查詢一次數據庫就好了。

處理大文件

若是一個數據量特別大(大於16M),好比讀入一個100多M的mp4文件。這種狀況下就須要用到GRIDFS.原理就是把他分割成一個一個小的塊

相關文章
相關標籤/搜索