1. 程式人生 > >MongoDB:12-MongoDB 資料庫引用(DBRefs vs 手動引用)

MongoDB:12-MongoDB 資料庫引用(DBRefs vs 手動引用)

資料庫引用的意義:

  1. mongodb中資料的掃描是按行來掃描的,這意味著如果有一個欄位的值長度很長,
  2. mongodb不會自動跳過而是將整個文件掃描一遍,當資料量十分密集而這個很長的欄位不需要經常被檢索時會嚴重拖慢效率,
  3. 因此此時可以將其作為引用儲存在其他的集合中
資料庫關係
  1. 在傳統的SQL資料庫中,關係被分為一個個表(table),在表中,每個資料項以主鍵(primary key)標識,
  2. 而一個表的主鍵又作為另一個表的外來鍵(reference key),在兩個表之間引用。
  3. 當遇上多對多關係的時候,
  4. 還需要一個額外的關聯表(reference table),將多對多關係轉化成兩個一對多關係。
  5. 而在MongoDB
    中,表示關係有兩種辦法:
    1. 一種是巢狀(embedded),既是將一個文件包裹一個子文件;
    2. 而另一種是引用連結(reference link),使用MongoDBDBRef物件建立文件和文件之間的關係。
  6. 除此之外,MongoDB的關係可以有111N N1 NN 幾種關係。
  1. 巢狀
  2. 每個MongoDB文件都由BSON文件組成,有類似JSON格式一樣的資料型別,
  3. 其中StringIntFloat稱為基本型別(或常量),
  4. HashArray稱之為複合型別。
  5. 所謂的巢狀,就是說文件中,利用複合型別,包裹一個多或多個其他型別的值,這些值稱之為子文件。
  6. 文件巢狀的數量和深度沒有限制MongoDB
    目前版本限制一個文件最大為16MB
  1. 引用連結
  2. 比起巢狀,引用連結更接近傳統意義上的(也就是,關係型資料庫術語中的)“引用”,它是兩個文件之間的一種關係。
  3. 引用連結通過DBRef物件建立,DBRef物件儲存瞭如何找到目標文件的資訊,
  4. 就像現實世界中的門牌號碼一樣(也類似關係型資料庫中的外來鍵)。
  5. 如果在一個文件A中,有一個DBRef物件,而這個DBRef物件儲存了關於如何找到文件B的資訊,
  6. 那麼文件A就可以通過解釋這個DBRef物件(稱之為解引用)來獲取文件B的資料。
什麼時候使用DBRef
  1. MongoDB中表示這種對其他文件的引用關係,並不是只有DBRef方式.
    1. 兩個集合 users(使用者),
      notes(筆記),
    2. 使用者可以建立筆記,筆記可以引用使用者或者別的筆記.
    3. db.users.insert({"_id":"refactor","displayName":"dis_refactor"})
    4. db.users.insert({"_id":"refactor2","displayName":"dis_refactor2"})
    5. db.notes.insert({"_id":2,"author":"refactor","text":"refactor in mongodb"})
    6. db.notes.insert(
    7. {
    8. "_id":22,
    9. "author":"refactor22",
    10. "text":"...DBRef likes url",
    11. "references":
    12. [
    13. {"$ref":"users","$id":"refactor"},
    14. {"$ref":"notes","$id":2}
    15. ]
    16. }
    17. )
    18. var note=db.notes.findOne({"_id":22});
    19. note.references.forEach(
    20.   function(ref){
    21.     printjson(db[ref.$ref].findOne({"_id":ref.$id}));
    22. });
  2. 上面的例子就用了另外一種引用:每個noteauthor鍵僅儲存了author文件的"_id"鍵,沒有必要用DBRef,
  3. 因為已經知道每個author就是users集合裡面的一個文件.
  4. 這種引用在GridFS的塊文件中"files_id"鍵僅僅就是對文件"_id"的引用.
  5. 在儲存引用的時候是選擇DBRef還是至儲存"_id"?
  6. 儲存"_id"會更加緊湊,對開發者而言就很輕量.
    1. 但是DBRef能夠引用任意集合(甚至是任意資料庫)的文件,開發者不必知道和記住被引用的文件在哪些集合裡面.
    2. 驅動程式和一些工具對DBRef提供了額外的功能(如自動去引用).
    1. 總之,儲存一些對不同集合的文件的引用時,最好用DBRef.否則最好儲存"_id"作為引用來使用,這樣更簡單,也更容易操作.
引用分類:
  1. MongoDB使用引用來規範資料結構文件。
    1. http://blog.csdn.net/fly910905/article/details/78279851
  2. MongoDB引用有兩種:
    1. 手動引用(ManualReferences
    2. DBRefs
DBRefs vs 手動引用
  1. 考慮這樣的一個場景,我們在不同的集合中(address_home, address_office, address_mailing,等)
  2. 儲存不同的地址(住址,辦公室地址,郵件地址等)。
  3. 這樣,我們在呼叫不同地址時,也需要指定集合,一個文件從多個集合引用文件,我們應該使用DBRefs
使用 DBRefs
  1. DBRef的形式:
    1. { $ref :, $id :, $db :}
  2. 三個欄位表示的意義為:
    1. $ref:集合名稱
    2. $id:引用的id
    3. $db:資料庫名稱,可選引數

以下例項中使用者資料文件使用了 DBRef, 欄位 address:

  1. {
  2. "_id":ObjectId("53402597d852426020000002"),
  3. "address":{
  4. "$ref":"address_home",
  5. "$id":ObjectId("534009e4d852427820000002"),
  6. "$db":"w3cschoolcc"},
  7. "contact":"987654321",
  8. "dob":"01-01-1991",
  9. "name":"Tom Benzamin"
  10. }

address DBRef 欄位指定了引用的地址文件是在 address_home 集合下的 w3cschoolcc 資料庫,id 為 534009e4d852427820000002。

以下程式碼中,我們通過指定 $ref 引數(address_home 集合)來查詢集合中指定id的使用者地址資訊:

  1. >var user = db.users.findOne({"name":"Tom Benzamin"})
  2. >var dbRef = user.address
  3. >db[dbRef.$ref].findOne({"_id":(dbRef.$id)})

以上例項返回了 address_home 集合中的地址資料:

  1. {
  2. "_id":ObjectId("534009e4d852427820000002"),
  3. "building":"22 A, Indiana Apt",
  4. "pincode":123456,
  5. "city":"Los Angeles",
  6. "state":"California"
  7. }