使用SequelizeJS使用外键编写迁移

sli*_*fty 24 database-migration node.js sequelize.js

的背景

我正在用SequelizeJS构建一个项目,是一个流行的NodeJS ORM.在设计架构时,似乎有两种策略:

  1. 创建模型代码并使用.sync()函数自动为模型生成表.
  2. 使用QueryInterfaceumzug创建模型代码并编写手动迁移.

我的理解是#1对于快速原型设计更好,但对于预计会随着时间的推移而发展并且生产数据需要能够在迁移中存活的项目而言,#2是最佳实践.

这个问题与策略#2有关.

问题

我的表有必须通过外键反映的关系.

  • 如何通过Sequelize QueryInterface创建具有外键关系的表?

  • Sequelize需要哪些列和帮助程序表?例如,似乎需要特定的列,例如createdAt或updatedAt.

sli*_*fty 28

如何通过Sequelize QueryInterface创建具有外键关系的表?

.createTable()方法接受列的字典.您可以在文档中查看.define()有效属性列表,特别是通过查看[attributes.column.*]params表中的行.

要创建具有外键关系的属性,请使用"references"和"referencesKey"字段:

例如,以下内容将创建一个users表,以及一个user_emails引用users表的表.

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' }
    }
  })
});
Run Code Online (Sandbox Code Playgroud)

sequelize需要哪些列和帮助程序表?例如,似乎需要特定的列,例如createdAt或updatedAt.

看来,一个标准模型将期望的id,updatedAtcreatedAt每个表列.

queryInterface.createTable('users', {
  id: {
    type: Sequelize.INTEGER,
    primaryKey: true,
    autoIncrement: true
  },
  createdAt: {
    type: Sequelize.DATE
  },
  updatedAt: {
    type: Sequelize.DATE
  }
}
Run Code Online (Sandbox Code Playgroud)

如果设置paranoidtrue模型,则还需要deletedAt时间戳.

  • 对于在此结束的人来说,这个答案很好,但语法现已弃用,请使用以下内容:_references:{model:'users',key:'id'} _ (5认同)

Sha*_*dit 9

这是创建用于添加列的迁移文件。

这里我想在users表中添加一个列area_id。运行命令:

sequelize migration:create --name add-area_id-in-users
Run Code Online (Sandbox Code Playgroud)

一旦它被执行,就会在迁移文件夹中创建一个迁移文件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'),
        ]);
      }
    };
Run Code Online (Sandbox Code Playgroud)

在用户表中,我将创建一个名为 region_id 的列以及类型和关系/外键/引用。就是这样。


gal*_*lki 6

我想提供另一个更多的手动替代方案,因为在使用手动迁移和queryInterface时,我遇到了以下问题:迁移文件夹中有2个文件,如此

migrations/create-project.js
migrations/create-projectType.js
Run Code Online (Sandbox Code Playgroud)

因为它引用project了列,由于文件的顺序而没有创建,这导致了错误.projectTypeIdprojectType

我通过在创建两个表之后添加外键约束来解决它.在我的情况下,我决定写在里面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',
}))
Run Code Online (Sandbox Code Playgroud)

  • 好的!一个注意事项 - 您可能需要考虑使用顺序命名迁移以开始文件名,以确保无论表名称如何(例如`01-create-projecttype.js`,`02-create-project .js`)。这也很重要,因为当您编辑/添加表时,您可以保持旧的迁移步骤保持原状(例如`03-edit-projecttype.js`)。 (2认同)