最主要的当然是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;
重要的部分是事务BEGIN 和COMMIT 在创建数据时包装所有这些INSERT 语句。即使没有实现事务,您仍然会看到这两个项目与相关的“父项”一起创建。但争论的重点是这是您“应该”实施交易的地方。
另请注意,用于数据创建和后续访问的"aliased" Menu 实际上并不是“必需”包含在include 选项的.create() 方法中。它是“可选的”,并且已经在 .hasMany() 参数下定义,所以你真的不需要再做一次了。
即使你这样做了,那么该部分仍然是与 model 参数一起使用的“关联”:
{
include: {
model: MainMenu.Meals,
as: 'Menu'
},
transaction
}
所以不要将其与引用的“表”模型的原始名称混淆,这也可能是另一个混淆点。