我应该让 Sequelize 模型和迁移保持同步吗?

Posted

技术标签:

【中文标题】我应该让 Sequelize 模型和迁移保持同步吗?【英文标题】:Am i supposed to keep Sequelize models and migrations in sync? 【发布时间】:2020-09-07 05:08:26 【问题描述】:

总的来说,我是 Sequelize.js 和数据库的新手,我以前没有使用过迁移,但我知道它们可以用于以非破坏性方式更改表结构。

但是我不确定在哪里声明列选项(notNull、引用、验证、ENUM 值等...)

我应该在模型文件或迁移文件中声明这些选项吗?或两者?

在模型和迁移中添加选项不会导致重复代码吗?

(请记住,我说的是为数据库创建表的初始迁移,而不是添加列和内容的迁移......)

任何帮助将不胜感激!

【问题讨论】:

相关:***.com/questions/21105748/… 【参考方案1】:

我看到您可以采取三种选择。前两个选项可能是极端情况,但有助于理解。

破坏性选项

您想要为项目制作原型并且不介意丢失数据,那么您可能不关心迁移文件并根据您的模型同步您的数据库:

await sequelize.sync( force: true );

它将在您的所有模型上执行:

DROP TABLE IF EXISTS "your_model" CASCADE;
CREATE TABLE IF NOT EXISTS "your_model" (...)

例如,此命令可以在您的应用程序启动时执行。


 静态选项

正如您提到的,您不想添加列和内容,这可能是一个不错的选择。

现在,如果您不想丢失数据,可以简单地使用不带强制选项的同步方法:

await sequelize.sync( );

它只会生成:

CREATE TABLE IF NOT EXISTS "your_model" (...)

因此,您的表是根据您的模型创建的,您不必创建迁移文件。

但是,如果您想修改模型并且这是最常见的用例,新列将不会在表中动态生成,这就是您需要迁移脚本的原因。


灵活的选择

您必须同时定义迁移文件和模型。这就是cli 所做的。这是一个例子:

# npx sequelize-cli init or create migrations and models folders
npx sequelize-cli model:generate --name User --attributes firstName:string,email:string

现在您将拥有另外两个文件:

// migrations/<date>-create-user.js
module.exports = 
  up: (queryInterface, Sequelize) => 
    return queryInterface.createTable('Users', 
      id: 
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      ,
      firstName: 
        type: Sequelize.STRING
      ,
      email: 
        type: Sequelize.STRING
      ,
      createdAt: 
        allowNull: false,
        type: Sequelize.DATE
      ,
      updatedAt: 
        allowNull: false,
        type: Sequelize.DATE
      
    );
  ,
  down: (queryInterface, Sequelize) => 
    // I usually remove this and create the table only if not exists
    return queryInterface.dropTable('Users'); 
  
;
// models/users.js
module.exports = (sequelize, DataTypes) => 
  const User = sequelize.define('User', 
    firstName: DataTypes.STRING,
    email: DataTypes.STRING
  , );
  User.associate = function(models) 
    // associations can be defined here
  ;
  return User;
;

您可以从迁移和模型中重构代码,但这会相当麻烦,因为某些迁移文件只会添加一列,因此将它们全部合并到模型中可能不太清楚。

【讨论】:

【参考方案2】:

您应该在两者中都这样做,因为随着时间的推移,您的模型和初始迁移会彼此不同。所以我想你应该确定模型中的最终结构,然后创建初始迁移。

【讨论】:

【参考方案3】:

约束在 SQL 级别定义和运行,而验证在应用程序级别运行。 Sequelize 支持对模型进行验证和约束,只能在迁移中定义约束。

我的意见是将所有约束放在迁移中,并将验证放在模型中。这样,您就有了某种关注点分离,因为在对数据库进行查询之前运行验证 - 运行约束。你可以阅读更多关于 Sequelize 的验证和约束Validations and Constraints

【讨论】:

以上是关于我应该让 Sequelize 模型和迁移保持同步吗?的主要内容,如果未能解决你的问题,请参考以下文章

即使 paranoid 设置为 true,Sequelize.js 仍会删除表行

使用 sequelize 和 typescript 进行自动迁移

Sequelize - 模型和迁移

sequelize 模型、迁移文件和外键。哪一个是对的?

如何从 Sequelize 模型自动生成迁移

使用随时间变化的模型为 Sequelize 制作可重现的迁移字符串?