2015-04-29 57 views
2

我爲我的web應用程序使用了mongodb和mongoose。網絡應用程序用於註冊游泳比賽,每場比賽可以進行X次比賽。我的數據結構截至目前:子文檔動態大小mongodb

{ 
    "_id": "1", 
    "name": "Utmanaren", 
    "location": "town", 
    "startdate": "20150627", 
    "enddate": "20150627" 
    "race" : { 
    "gender" : "m" 
    "style" : "freestyle" 
    "length" : "100" 
    } 
} 

這樣做,我需要確定和定義每場比賽的比賽數量。我試過的一個解決方案是有一個單獨的文件,並有一個比賽屬於一個Id,如下所示。

{ 
    "belongsTOId" : "1" 
    "gender" : "m" 
    "style" : "freestyle" 
    "length" : "100" 
} 
{ 
    "belongsTOId" : "1" 
    "gender" : "f" 
    "style" : "butterfly" 
    "length" : "50" 
} 

在使用Mongodb時,有沒有一種方法可以創建和定義動態的比賽作爲子文檔?

謝謝!

+1

您可以將比賽場作爲數組添加並將比賽記錄推送到比賽場。 –

+0

Ahh okey,所以我會使用$ push並將新增的種族推到結構中? @İlkerKorkut – bark

+0

是@bark,我在我的評論中發送了我想說的答案。 –

回答

2

基本上有兩種建模數據結構的方法;您可以設計一個可以引用或嵌入比賽文檔的模式。

讓我們考慮下面的例子,它將游泳比賽和多種族關係進行映射。這證明了如果需要在另一個上下文中查看許多數據實體,則通過嵌入引用的優勢。在競爭和種族之間的數據這一個一對多的關係,競爭有多個種族實體:

// db.competition schema 
{ 
    "_id": 1, 
    "name": "Utmanaren", 
    "location": "town", 
    "startdate": "20150627", 
    "enddate": "20150627" 
    "races": [ 
     { 
      "gender" : "m" 
      "style" : "freestyle" 
      "length" : "100" 
     }, 
     {   
      "gender" : "f" 
      "style" : "butterfly" 
      "length" : "50" 
     } 
    ] 
} 

隨着嵌入式數據模型,應用程序可以檢索只用一個查詢完整的游泳比賽資料。這種設計還有其他優點,其中之一就是數據局部性。由於MongoDB將數據連續存儲在磁盤上,因此將所需的所有數據放在一個文檔中可確保旋轉磁盤在磁盤上尋找特定位置所需的時間更少。嵌入式文檔的另一個優點是寫入數據時的原子性和隔離性。爲了說明這一點,說要刪除其具有價值的「蝴蝶」賽跑「風格」屬性的競爭,這可以通過一個單一的(原子)操作來完成:

db.competition.remove({"races.style": "butterfly"}); 

有關數據建模的詳細信息在MongoDB中,請閱讀文檔Data Modeling Introduction,特別是Model One-to-Many Relationships with Embedded Documents

另一個設計選擇是引用文檔遵循規範化模式,其中競賽文件包含對比賽的某一個文件:

// db.race schema 
{ 
    "_id": 1, 
    "competition_id": 1, 
    "gender": "m", 
    "style": "freestyle", 
    "length": "100" 
}, 
{ 
    "_id": 2, 
    "competition_id": 1, 
    "gender": "f", 
    "style": "butterfly", 
    "length": "50" 
} 

上述方法提高了執行查詢的靈活性。例如,檢索所有的孩子的比賽文件,其中主父實體competition具有ID 1將是簡單,只需創建針對集合race查詢:

db.race.find({"competiton_id": 1}); 

使用文檔的參考方法也以上規範化模式有優勢當你與非常不可預測的團隊之間有一對多的關係時。如果每個給定的competition有幾百或幾千個race文檔,嵌入選項就空間約束而言有很多挫折,因爲文檔越大,它使用的RAM越多,MongoDB文檔的硬核大小限制爲16MB。

如果您的應用程序經常使用競爭信息檢索競賽數據,那麼您的應用程序需要發出多個查詢來解析引用。

一般的經驗法則是,如果您的應用程序的查詢模式是衆所周知的,並且數據往往只能以一種方式訪問​​,那麼嵌入式方法就可以很好地工作。如果您的應用程序以多種方式查詢數據,或者無法預測數據查詢模式,則更適合這種情況的更規範化的文檔引用模型。

價:

MongoDB Applied Design Patterns: Practical Use Cases with the Leading NoSQL Database By Rick Copeland

+1

謝謝!這幫助我瞭解:) – bark

0

你基本上想要更新數據,所以你應該插入基本上是子文檔鍵更新的數據。

  1. 在主文檔中保留一個鍵數組。
  2. 插入子文檔並將該鍵添加到列表或更新列表。
0

爲推動單個項目到田間

db.yourcollection.update({ $push: { "races": { "belongsTOId" : "1" , "gender" : "f" , "style" : "butterfly" , "length" : "50"} } }); 

要將多個項目推入字段,它允許在字段中重複;

db.yourcollection.update({ $push: { "races": { $each: [ { "belongsTOId" : "1" , "gender" : "f" , "style" : "butterfly" , "length" : "50"}, { "belongsTOId" : "2" , "gender" : "m" , "style" : "horse" , "length" : "70"} ] } } }); 

要推動多個項目沒有重複項目;

db.yourcollection.update({ $addToSet: { "races": { $each: [ { "belongsTOId" : "1" , "gender" : "f" , "style" : "butterfly" , "length" : "50"}, { "belongsTOId" : "2" , "gender" : "m" , "style" : "horse" , "length" : "70"} ] } } }); 

$ pushAll自2.4版本棄用,因此,我們在$push而不是$ pushAll使用$each

使用$ push時,您將能夠對項目進行排序和分片。您可能會檢查mongodb manual

+0

感謝您的幫助! – bark