背景
我正在使用 SequelizeJS 构建一个项目,这是一种流行的 NodeJS ORM。设计模式时,似乎有两种策略:
我的理解是,#1 更适合快速原型设计,但 #2 是预计随着时间的推移而发展以及生产数据需要能够在迁移中幸存的项目的最佳实践。
这个问题与策略#2有关。
问题
我的表具有必须通过外键反映的关系。
如何通过 Sequelize QueryInterface 创建相互具有外键关系的表?
Sequelize 需要哪些列和辅助表?例如,似乎需要特定的列,例如createdAt或updatedAt。
如何通过 Sequelize QueryInterface 创建相互具有外键关系的表?
.createTable()
方法接受列字典。您可以在 .define()
的 文档中查看有效属性列表,特别是通过查看参数表中的 [attributes.column.*]
行。
要创建具有外键关系的属性,请使用“引用”字段。
例如,以下命令将创建一个
users
表和一个引用用户表的 user_emails
表:
queryInterface.createTable('users', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
}
}).then(function() {
queryInterface.createTable('user_emails', {
userId: {
type: Sequelize.INTEGER,
references: { model: 'users', key: 'id' }
}
})
});
sequelize 需要哪些列和辅助表?例如,似乎需要特定的列,例如createdAt或updatedAt。
标准模型似乎需要每个表都有
id
、updatedAt
和 createdAt
列。
queryInterface.createTable('users', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
createdAt: {
type: Sequelize.DATE
},
updatedAt: {
type: Sequelize.DATE
}
}
paranoid
设置为 true
,则还需要 deletedAt
时间戳。
我想提供另一个更多手动替代方案,因为在使用手动迁移和queryInterface时,我遇到了以下问题:我在迁移文件夹中有2个文件,如下所示
migrations/create-project.js
migrations/create-projectType.js
因为
project
有列 projectTypeId
,它引用了 projectType
,由于文件的顺序,该列尚未创建,这导致了错误。
我通过在创建两个表后添加外键约束来解决这个问题。就我而言,我决定将其写在里面
create-projectType.js
:
queryInterface.createTable('project_type', {
// table attributes ...
})
.then(() => queryInterface.addConstraint('project', ['projectTypeId'], {
type: 'FOREIGN KEY',
name: 'FK_projectType_project', // useful if using queryInterface.removeConstraint
references: {
table: 'project_type',
field: 'id',
},
onDelete: 'no action',
onUpdate: 'no action',
}))
这是创建用于添加列的迁移文件。
这里我想在 users 表中添加一列 area_id 。运行命令:
sequelize migration:create --name add-area_id-in-users
执行后,会在迁移文件夹中创建一个迁移文件 timestamp-add-region_id-in-users。
在创建的迁移文件中粘贴以下代码:
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return Promise.all([
queryInterface.addColumn('users', 'region_id',
{
type: Sequelize.UUID,
references: {
model: 'regions',
key: 'id',
},
onUpdate: 'CASCADE',
onDelete: 'SET NULL',
defaultValue: null, after: 'can_maintain_system'
}),
]);
},
down: (queryInterface, Sequelize) => {
return Promise.all([
queryInterface.removeColumn('users', 'region_id'),
]);
}
};
在用户表中,我将创建一个名为region_id 的列以及类型和关系/外键/引用。就是这样。
因此,第一个问题如下所示,第二个问题:您无需明确提及
createdAt
和 updatedAt
,因为它们是由 Sequelize 为您生成的。
解决办法是:
queryInterface.createTable('Images', {
//...
}).then(
return queryInterface.addConstraint('Images', ['postId'], {
type: 'foreign key',
name: 'custom_fkey_images',
references: { //Required field
table: 'Posts',
field: 'id'
},
onDelete: 'cascade',
onUpdate: 'cascade'
})
)