2015-11-23 74 views
0

來自關係數據庫背景的Meteor和MongoDB的新手。這個問題實際上反映了我在MongoDB中處理關係的困惑。MongoDB - 插入兩個集合,一個集合引用另一個作爲子文檔

示例:我想將一個配方插入一組配方中,在這種情況下,這是一個逗號分隔的多個配料串。然而,我想要將這些成分同時加入到一系列成分中。我希望食譜指的是成分集合中的成分,例如,如果我第一次得到某個成分的拼寫錯誤,我可以稍後在成分集合中更新它,並且使用該成分的所有配方也更新了。

看來,這樣做的方法是將成分集合作爲子文檔包含在食譜集合中。

但是,我不知道我該如何實際執行該操作。使用流星在JS代碼示例如下:

Recipes = new Mongo.Collection("recipes"); 
Ingredients = new Mongo.Collection("ingredients"); 

Template.body.events({ 
    "submit .new-recipe": function(event) { 
     // Prevent default browser form submit 
     event.preventDefault(); 

     // Get value from form element 
     var text = event.target.text.value; 
     var splitText = text.split(","); 
     var nInputs = splitText.length; 
     var recipe = []; 
     for (var i = 0; i < nInputs; i++) { 
      // Insert an ingredient into the ingredients collection 
      Ingredients.insert({ 
       itemName: splitText[i].trim(), 
       createdAt: new Date() 
      }); 
      recipe.push(splitText[i]); 
     } 
     // Insert the list of ingredients as a recipe into the recipes collection 
     Recipes.insert({ 
      recipe: recipe, 
      createdAt: new Date() 
     }); 
     // Clear form 
     event.target.text.value = ""; 
    } 
}); 

顯然,上述不正確地做這項工作。它切斷了配料和配方之間的關係。但我如何維持這種關係呢?插入配料時,我是否會將配料中的各種配料放入食譜集合中?在插入配料時,我是否將整個配料文檔作爲配方文檔的一部分插入配方集合中?

回答

2

聽起來你需要兩個集合之間的簡單關係模型。這通常通過將一個集合的_id作爲另一個值存儲來實現。在你的情況下,我建議將配料ID作爲數組存儲在配方中。我在初次嘗試中發現了幾個問題:

  1. 在插入之前未檢查配料的存在。所以兩個使用「糖」的食譜會插入兩個糖文件 - 我認爲這不是你的意圖。

  2. 插入發生在客戶端,但除非您要發佈您的整個配料集合,否則客戶不能成爲實際存在配料的權威(從開始)。

  3. 您在插入時使用客戶端的時間戳。如果他們的時鐘錯誤怎麼辦?實際上有a package處理這個,但我們可以使用一種方法解決所有上述問題。


我建議拆分客戶端上的文本輸入,然後發出Meteor.call('recipes.insert', ingredientNames),該方法的實現看起來是這樣的:

Meteor.methods({ 
    'recipes.insert': function(ingredientNames) { 
    // Make sure the input is an array of strings. 
    check(ingredientNames, [String]); 

    // Use the same createdAt for all inserted documents. 
    var createdAt = new Date; 

    // Build an array of ingredient ids based on the input names. 
    var ingredientIds = _.map(ingredientNames, function(ingredientName) { 
     // Trim the input - consider toLowerCase also? 
     var name = ingredientName.trim(); 

     // Check if an ingredient with this name already exists. 
     var ingredient = Ingrediends.findOne({itemName: name}); 
     if (ingredient) { 
     // Yes - use its id. 
     return ingredient._id; 
     } else { 
     // Insert a new document and return its id. 
     return Ingrediends.insert({ 
      itemName: name, 
      createdAt: createdAt 
     }); 
     } 
    }); 

    // Insert a new recipe using the ingredient ids to join the 
    // two collections. 
    return Recipes.insert({ 
     ingredientIds: ingredientIds, 
     createdAt: createdAt 
    }); 
    } 
}); 

推薦閱讀:

+0

非常感謝!除了'check(ingredientNames,[String]);'行之外,一切都可以工作。錯誤消息說「檢查」是一個未知的功能。我錯過了什麼?它來自一些JS庫嗎? – MichM

+0

那很奇怪。 [檢查](HTTP://docs.meteor。com /#/ full/check)是一個默認包含的軟件包。你是否正在運行一個真正舊版本的流星? –

+0

感謝您的線索!通過「流星加檢查」解決 – MichM

相關問題