使用 SequelizeJS 编写带有外键的迁移
Writing Migrations with Foreign Keys Using SequelizeJS
背景
我正在使用 SequelizeJS 构建一个项目,这是一个流行的 NodeJS ORM。在设计模式时,似乎有两种策略:
- 创建模型代码并使用 .sync() 函数自动为您的模型生成表。
- 创建模型代码并写入manual migrations using QueryInterface and umzug。
我的理解是#1 更适合快速原型制作,但#2 是预期随着时间的推移而发展的项目以及生产数据需要能够在迁移中生存的项目的最佳实践。
这个问题属于策略#2。
问题
我的表具有必须通过外键反映的关系。
如何通过 Sequelize QueryInterface 创建彼此具有外键关系的表?
Sequelize 需要哪些列和辅助表?例如,似乎需要特定的列,例如 createdAt 或 updatedAt。
How do I create tables with foreign key relationships with one another through the Sequelize QueryInterface?
.createTable()
方法接收列字典。您可以在 documentation for .define()
中查看有效属性列表,特别是通过查看参数 table.
中的 [attributes.column.*]
行
要创建具有外键关系的属性,请使用“references”和“referencesKey”字段:
例如,以下将创建一个 users
table 和一个 user_emails
table 来引用用户 table.
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' }
}
})
});
What columns and helper tables are required by sequelize? For example, it appears that specific columns such as createdAt or updatedAt are expected.
标准模型似乎需要每个 table、updatedAt
和 createdAt
列。
queryInterface.createTable('users', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
createdAt: {
type: Sequelize.DATE
},
updatedAt: {
type: Sequelize.DATE
}
}
如果您在模型上设置 paranoid
to true
,您还需要一个 deletedAt
时间戳。
我想提供另一种更多手动选择,因为在使用手动迁移和查询接口时,我运行遇到以下问题:我在迁移文件夹中有 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',
}))
所以第一个是下面的解决方案,第二个问题:你不需要明确提到 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'
})
)
这是创建用于添加列的迁移文件。
这里我想在userstable中添加一列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'),
]);
}
};
在用户 table 中,我将创建一个名为 region_id 的列以及类型和 relation/foreign key/references。就是这样。
背景
我正在使用 SequelizeJS 构建一个项目,这是一个流行的 NodeJS ORM。在设计模式时,似乎有两种策略:
- 创建模型代码并使用 .sync() 函数自动为您的模型生成表。
- 创建模型代码并写入manual migrations using QueryInterface and umzug。
我的理解是#1 更适合快速原型制作,但#2 是预期随着时间的推移而发展的项目以及生产数据需要能够在迁移中生存的项目的最佳实践。
这个问题属于策略#2。
问题
我的表具有必须通过外键反映的关系。
如何通过 Sequelize QueryInterface 创建彼此具有外键关系的表?
Sequelize 需要哪些列和辅助表?例如,似乎需要特定的列,例如 createdAt 或 updatedAt。
How do I create tables with foreign key relationships with one another through the Sequelize QueryInterface?
.createTable()
方法接收列字典。您可以在 documentation for .define()
中查看有效属性列表,特别是通过查看参数 table.
[attributes.column.*]
行
要创建具有外键关系的属性,请使用“references”和“referencesKey”字段:
例如,以下将创建一个 users
table 和一个 user_emails
table 来引用用户 table.
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' }
}
})
});
What columns and helper tables are required by sequelize? For example, it appears that specific columns such as createdAt or updatedAt are expected.
标准模型似乎需要每个 table、updatedAt
和 createdAt
列。
queryInterface.createTable('users', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
createdAt: {
type: Sequelize.DATE
},
updatedAt: {
type: Sequelize.DATE
}
}
如果您在模型上设置 paranoid
to true
,您还需要一个 deletedAt
时间戳。
我想提供另一种更多手动选择,因为在使用手动迁移和查询接口时,我运行遇到以下问题:我在迁移文件夹中有 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',
}))
所以第一个是下面的解决方案,第二个问题:你不需要明确提到 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'
})
)
这是创建用于添加列的迁移文件。
这里我想在userstable中添加一列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'),
]);
}
};
在用户 table 中,我将创建一个名为 region_id 的列以及类型和 relation/foreign key/references。就是这样。