使用Include Sequelize创建

时间:2018-04-14 07:09:18

标签: javascript node.js sequelize.js

最近我在sequelize文档中发现this,您可以使用include创建。现在我尝试在我的程序上执行它,但只创建“父”模型的记录而不是子项。

这是我的模特和我的控制器。

var MainMenu = sequelize.define('MainMenu', {
    Name: {
      type: DataTypes.STRING(50)      
    },
    Day: {
      type: DataTypes.DATE
    },
    RecordStatus:{
      type: DataTypes.BOOLEAN,
      defaultValue: true
    },    
    DeletedAt: {
      type: DataTypes.DATE
    }
  },
  {
    associate: function(models){
      models.MainMenu.hasMany(models.MainMeal, {as: 'Menu'});
    }
  }
);

exports.createIn = (req, res) => {

 let Menu = {
   Name: 'MenuTest',
   MainMeal: [{
     Type: 'Breakfast',
     Name: 'MealTest1'
   }, {
     Type: 'Lunch',
     Name: 'MealTest2'
   }]
 };

  db.MainMenu.create(Menu, {
    include: [{
      model: db.MainMeal,
      as: 'Menu'
    }]
  })
    .then( mainmenu => {
      if (!mainmenu) {
        return res.send('users/signup', {
          errors: 'Error al registrar el mainmenu.'
        });
      } else {
        return res.jsonp(mainmenu);
      }
    })
    .catch( err => {
      console.log(err);
      return res.status(400)
        .send({
          message: errorHandler.getErrorMessage(err)
        });
    });
};

在我的情况下,它只创建MainMenu记录,而不是MainMeal记录。我做错了什么?

2 个答案:

答案 0 :(得分:2)

更改您的menu对象,并添加Menu数组,而不是MainMeal

  
      
  • 您必须在对象
  • 中提供别名   
let mainMenu = {
   Name: 'MenuTest',
   Menu: [{
     Type: 'Breakfast',
     Name: 'MealTest1'
   }, {
     Type: 'Lunch',
     Name: 'MealTest2'
   }]
 };

现在,

db.MainMenu.create(mainMenu, {
    include: [{
      model: db.MainMeal,
      as: 'Menu'
    }]
  })
    .then( mainmenu => {
      if (!mainmenu) {
        return res.send('users/signup', {
          errors: 'Error al registrar el mainmenu.'
        });
      } else {
        return res.jsonp(mainmenu);
      }
    })
    .catch( err => {
      console.log(err);
      return res.status(400)
        .send({
          message: errorHandler.getErrorMessage(err)
        });
    });

答案 1 :(得分:1)

主要的事情当然是Menu的命名应该是传递给.create()本身的数据,以及那里提供的参数和如果你真的需要指定别名“两次”,您不需要。但还有其他一些事情需要注意。

我个人更喜欢将关联存储为自己的导出,并将其包含在语句中。当您稍后了解该关联的用法时,这通常会变得更加清晰。

我还强烈建议您在跨多个表“编写”内容时,然后实施transactions以确保实际创建所有相关项目,并且在出现任何错误时不会将其孤立。

作为基于示例的简要列表:

const Sequelize = require('sequelize');

const sequelize = new Sequelize('sqlite:menu.db',{ logging: console.log });

const MainMeal = sequelize.define('MainMeal', {
  Type: { type: Sequelize.STRING(50) },
  Name: { type: Sequelize.STRING(50) }
});

const MainMenu = sequelize.define('MainMenu', {
  Name: { type: Sequelize.STRING(50) }
});

MainMenu.Meals = MainMenu.hasMany(MainMeal, { as: 'Menu' });

(async function() {

  try {

    await sequelize.authenticate();
    await MainMeal.sync({ force: true });
    await MainMenu.sync({ force: true });

    let result = await sequelize.transaction(transaction => 
      MainMenu.create({
        Name: 'MenuTest',
        Menu: [
          { Type: 'Breakfast', Name: 'MealTest1' },
          { Type: 'Lunch', Name: 'MealTest2' }
        ]
      },{
        include: MainMenu.Meals,
        transaction
      })
    );

  } catch(e) {
    console.error(e);
  } finally {
    process.exit();
  }
})();

会输出类似的内容:

Executing (default): SELECT 1+1 AS result
Executing (default): DROP TABLE IF EXISTS `MainMeals`;
Executing (default): CREATE TABLE IF NOT EXISTS `MainMeals` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `Type` VARCHAR(50), `Name` VARCHAR(50), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, `MainMenuId` INTEGER REFERENCES `MainMenus` (`id`) ON DELETE
SET NULL ON UPDATE CASCADE);
Executing (default): PRAGMA INDEX_LIST(`MainMeals`)
Executing (default): DROP TABLE IF EXISTS `MainMenus`;
Executing (default): CREATE TABLE IF NOT EXISTS `MainMenus` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `Name` VARCHAR(50), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL);
Executing (default): PRAGMA INDEX_LIST(`MainMenus`)
Executing (3d645847-56ca-435a-b786-6be62a05e8d5): BEGIN DEFERRED TRANSACTION;
Executing (3d645847-56ca-435a-b786-6be62a05e8d5): INSERT INTO `MainMenus` (`id`,`Name`,`createdAt`,`updatedAt`) VALUES (NULL,'MenuTest','2018-04-14 08:08:17.132 +00:00','2018-04-14 08:08:17.132 +00:00');
Executing (3d645847-56ca-435a-b786-6be62a05e8d5): INSERT INTO `MainMeals` (`id`,`Type`,`Name`,`createdAt`,`updatedAt`,`MainMenuId`)
VALUES (NULL,'Breakfast','MealTest1','2018-04-14 08:08:17.152 +00:00','2018-04-14 08:08:17.152 +00:00',1);
Executing (3d645847-56ca-435a-b786-6be62a05e8d5): INSERT INTO `MainMeals` (`id`,`Type`,`Name`,`createdAt`,`updatedAt`,`MainMenuId`)
VALUES (NULL,'Lunch','MealTest2','2018-04-14 08:08:17.153 +00:00','2018-04-14 08:08:17.153 +00:00',1);
Executing (3d645847-56ca-435a-b786-6be62a05e8d5): COMMIT;

创建数据时,事务BEGINCOMMIT包含所有这些INSERT语句的重要部分。即使没有实现交易,您仍然会看到两个项目与相关的“父”一起创建。但问题的关键在于,这是“应该”实施交易的地方。

另请注意,数据创建和后续访问中使用的"aliased" Menu实际上并非“必须”包含在{{1}的.create()方法中}} 选项。它是“可选的”,并且已在include参数下定义,因此您不需要再次执行此操作。

即使您这样做了,那么该部分仍然是与.hasMany()参数一起使用的“关联”:

model

因此,不要将被引用的“表格”的模型的原始名称混淆,这也可能是另一个混​​淆点。