node.js - 尝试以多对多关系创建一个实例和多个相关实例

标签 node.js postgresql express sequelize.js

我正在尝试使用联结表创建一个实例和多个具有多对多关系的相关实例。

在创建多个相关实例时,我还需要为联结表上的属性添加一个值。我不知道是不是我对 sequelize 或 promises 的了解不足导致了我的问题。

我使用的代码如下。此代码确实将项目添加到数据库,但我需要在操作完成后重定向,这是行不通的。

基本上,我需要创建一个食谱。创建后,我需要创建成分并将它们与该食谱相关联。成分存储在来自 HTML 页面上的表单的数组中。在关联成分时,我需要将 ingredient_quantity 添加到 RecipeIngredients 表,这是关系的直通部分(联结表)。

global.db.Recipe.belongsToMany(
    global.db.Ingredient, 
    { 
        as: 'Ingredients', 
        through: global.db.RecipeIngredients, 
        foreignKey: 'recipe_id' 
    });
global.db.Ingredient.belongsToMany(
    global.db.Recipe, 
    { 
        as: 'Recipes', 
        through: global.db.RecipeIngredients, 
        foreignKey: 'ingredient_id' 
    });

router.post('/new', ensureLoggedIn, bodyParser.json(), function (req, res) {
    var recipeName = req.body.recipe_name;
    var steps = req.body.steps;
    var ingredients = req.body.ingredients;
    var ingredientQty = {};
    var currentIngredient;
    var ingredientsToAdd = [];

    db.Recipe.create({
        recipe_name: recipeName,
        directions: steps,
        FamilyId: req.user.FamilyId,
        CreatedBy: req.user._id
    })
    .then(function (recipe) {
        for (var i = 0; i < ingredients.length; i++) {

            currentIngredient = ingredients[i];
            ingredientQty[currentIngredient.ingredient_name] = 
currentIngredient.quantity;

            db.Ingredient.findOrCreate({
                where: { 
                    ingredient_name: currentIngredient.ingredient_name, 
                    FamilyId: req.user.FamilyId 
                }
            })
            .spread(function (ingredient, created) {
                if (created) {
                    console.log("Added Ingredient to DB: " + 
                    currentIngredient.ingredient_name);
                }

            ingredient.Recipes = {
                ingredient_quantity: 
                    ingredientQty[ingredient.ingredient_name]
            };
            ingredient.CreatedBy = req.user._id;
            recipe.addIngredient(ingredient)
            .then(function () {
                console.log("Added Ingredient " + ingredient.ingredient_name 
                + " to Recipe " + recipe.recipe_name);
            });
        })
    }

})
.finally(function(recipe){
    res.redirect('/recipes');
});
});

如有任何帮助,我们将不胜感激。我知道我遇到了问题,因为我试图在循环内使用 promises,我只是不知道我还能如何做到这一点。

最佳答案

使用 sequelize,您可以一步创建对象及其关联对象,提供您正在创建的所有对象都是。这也称为嵌套创建。参见 this链接并向下滚动到标题为“使用关联创建”的部分

关于您的问题,RecipeIngredient 之间存在多对多关系,RecipeIngredients 是连接表.

假设您有一个要创建的新 Recipe 对象,例如:

var myRecipe = {
  recipe_name: 'MyRecipe',
  directions: 'Easy peasy',
  FamilyId: 'someId',
  CreatedBy: 'someUserId'
}

还有一组 Ingredient 对象,例如:

var myRecipeIngredients = [
  { ingredient_name: 'ABC', FamilyId: 'someId'},
  { ingredient_name: 'DEF', FamilyId: 'someId'},
  { ingredient_name: 'GHI', FamilyId: 'someId'}]

// associate the 2 to create in 1 step
myRecipe.Ingredients = myRecipeIngredients;

现在,您可以一步创建 myRecipe 及其关联的 myRecipeIngredients,如下所示:

Recipe.create(myRecipe, {include: {model: Ingredient}})
.then(function(createdObjects){
   res.json(createdObjects);
})
.catch(function(err){
   next(err);
});

就是这样!!
Sequelize 将在 Recipe 中创建 1 行,在 Ingredient 中创建 3 行,在 RecipeIngredients 中创建 3 行以将它们关联起来。

关于node.js - 尝试以多对多关系创建一个实例和多个相关实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43420533/

相关文章:

node.js - Azure的 Node 部署使用错误的 Node 和NPM

JavaScript,随机数的 Mocha 测试

javascript - 组件名称需要以大写字母开头?

sql - 从子查询更新表执行非常慢

Node.js:如何从回调中正确返回对象?

node.js - Chef 客户端在 node-gyp 重建时卡在 npm 安装上

sql - 找出对战次数最多的两支球队

ruby-on-rails - 带有初始数据的 docker postgres 不会在提交中持久化

node.js - 如何以驼峰式风格返回sequelize查询的结果集?

node.js - 为什么我的 express-server 仅通过浏览器支持 https 而不是通过其他 nodejs 脚本?