如何使用Sequelize CLI从Sequelize模型自动生成迁移?


80

我有一组Sequelize模型。我要使用迁移,而不是数据库同步。

根据本文的介绍Sequelize CLI似乎可以做到这一点:“当您使用CLI进行模型生成时,您还将免费获得迁移脚本。”

如何使用Sequelize CLI从现有Sequelize模型自动生成迁移?


2
“本文”链接无效。:(
Sunil Sharma

Answers:


48

如果您不想从头开始创建模型,则可以使用以下CLI命令手动生成迁移文件:

sequelize migration:generate --name [name_of_your_migration]

这将生成一个空白的框架迁移文件。尽管它不会将您的模型结构复制到文件中,但我确实比重新生成所有内容更轻松,更干净。注意:请确保从迁移目录的包含目录运行命令;否则,CLI将为您生成一个新的迁移目录


4
从来没有讨论过这一点,但是在进行迁移以添加或删除列时尤其需要,尤其是如果您想让后者稍后更新生产环境时。
BrinkDaDrink

4
您可以npx sequelize-cli migration:generate --name [name_of_your_migration]从项目的根目录运行。但是在您这样做之前,您需要告诉 sequelize-cli在何处生成迁移,sequelize-cli使用migrations-path为此配置的配置。 sequelize.org/master/manual/…–
Sento

8
这根本不能回答问题。它只是生成一个骨架,其中没有数据,这就是OP的要求
Carles Alcolea

2
谢谢,这真的很有用。无论如何,我们可以按OP的要求做,这真是太好了。
Claudio Novoa'4

44

您不能为现有模型创建迁移脚本。

资源:

如果采用经典方式,则必须通过CLI重新创建模型:

sequelize model:create --name MyUser --attributes first_name:string,last_name:string,bio:text

它将生成以下文件:

models / myuser.js:

"use strict";
module.exports = function(sequelize, DataTypes) {
  var MyUser = sequelize.define("MyUser", {
    first_name: DataTypes.STRING,
    last_name: DataTypes.STRING,
    bio: DataTypes.TEXT
  }, {
    classMethods: {
      associate: function(models) {
        // associations can be defined here
      }
    }
  });
  return MyUser;
};

migrations / 20150210104840-create-my-user.js:

"use strict";
module.exports = {
  up: function(migration, DataTypes, done) {
    migration.createTable("MyUsers", {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: DataTypes.INTEGER
      },
      first_name: {
        type: DataTypes.STRING
      },
      last_name: {
        type: DataTypes.STRING
      },
      bio: {
        type: DataTypes.TEXT
      },
      createdAt: {
        allowNull: false,
        type: DataTypes.DATE
      },
      updatedAt: {
        allowNull: false,
        type: DataTypes.DATE
      }
    }).done(done);
  },
  down: function(migration, DataTypes, done) {
    migration.dropTable("MyUsers").done(done);
  }
};


2
谢谢@Dor,我对使用sequelize进行同步功能的问题很少。据我了解,sequelize-cli在内部使用Umzug进行所有迁移。您显示的示例确实帮助我入门,但是Alter Table的过程是什么,假设我想在sequelize中更改MyUser模型,然后让sequelize cli为我创建迁移脚本,如何通过sequelize cli创建迁移脚本,经历所有模型更改。
Zeeshan 2015年1

16
通常,您需要在同步功能(适合新数据库或演示)和迁移之间进行区分。当您具有不断升级的生产系统并且不想丢失数据时,迁移可能是您唯一的选择。不幸的是,CLI仅适用于创建基本模板,它不运行任何特殊逻辑,也不扫描您的模型。(我对此也感到失望。)您需要创建迁移以转换架构/数据,并且需要将模型更改为代表最新的架构,就像过去那样。
Dor Rotman

5
感谢@Dor,但是为更改编写迁移脚本似乎需要大量工作。我希望以某种方式可以避免迁移脚本,并且默认情况下可以进行同步。
Zeeshan 2015年1

我也是。但是,如果您查看ActiveRecord和Entity Framework ORM,这也是它们实现的模式。
Dor Rotman

1
但是您链接到的视频确实表明他能够从现有模型创建迁移(请参见他stukko addMigration在5:40之后键入的时间)。
sebastien.b,2016年

31

现在是2020年,其中许多答案不再适用于Sequelize v4 / v5 / v6生态系统。

一个好的答案是说使用sequelize-auto-migrations,但说明性不足以在您的项目中使用。所以这里有更多颜色...

设定

我的团队使用了sequelize-auto-migrations因为原始回购尚未合并到一些关键PR。#56 #57 #58 #59

$ yarn add github:scimonster/sequelize-auto-migrations#a063aa6535a3f580623581bf866cef2d609531ba

编辑 package.json:

"scripts": {
  ...
  "db:makemigrations": "./node_modules/sequelize-auto-migrations/bin/makemigration.js",
  ...
}

处理

注意:请确保您正在使用git(或某些源代码管理)和数据库备份,以便在出现严重问题时可以撤消这些更改。

  1. 删除所有旧迁移(如果存在)。
  2. 关掉 .sync()
  3. 创建一个大型迁移,以迁移当前模型(yarn db:makemigrations --name "mega-migration")中的所有内容。
  4. 提交您01-mega-migration.js_current.json生成的内容。
  5. 如果您以前运行过.sync()或手写迁移,则需要通过将其名称插入SequelizeMeta表中来“伪造”大型迁移。INSERT INTO SequelizeMeta Values ('01-mega-migration.js')
  6. 现在您应该可以正常使用它了……
  7. 更改模型(添加/删除列,更改约束)
  8. $ yarn db:makemigrations --name whatever
  9. 提交您的02-whatever.js迁移和变化_current.json,和_current.bak.json
  10. 通过正常的sequelize-cli运行迁移$ yarn sequelize db:migrate
  11. 根据需要重复7-10

已知陷阱

  1. 重命名一列将变成一对removeColumnaddColumn。这将丢失生产中的数据。您将需要修改向上和向下操作以renameColumn代替使用。

对于那些对如何使用感到困惑的人renameColumn,该代码段将如下所示。(将切换为“ column_name_before”和“ column_name_after” rollbackCommands

{
    fn: "renameColumn",
    params: [
        "table_name",
        "column_name_before",
        "column_name_after",
        {
            transaction: transaction
        }
    ]
}
  1. 如果您进行了大量迁移,则down操作可能无法以一致的顺序完美删除项目。

  2. 该库的维护者不会主动对其进行检查。因此,如果开箱即用不适合您,则需要找到其他社区分支或其他解决方案。


我一直收到“ UNKNOWN_VALUE:未知值:大型迁移”错误。为什么会这样呢?
YulePale

1
哦。只是不要使用该--name选项。它是可选的。然后它将创建01-noname.js...,您可以手动重命名该文件。
PaulMest

1
经过数小时的困扰...谢谢!您
既是

1
嘿! 谢谢你 效果很好!:)帮助了我很多!我是node-express + Sequelize中的新手。
Glenn Posadas

1
这在v6上对我有用。唯一的失败点是Sequelize.NOW无法正确翻译,并在迁移时出现语法错误。除此之外,我没有问题。谢谢!
卢卡斯

25

现在,您可以使用npm软件包sequelize-auto-migrations自动生成迁移文件。https://www.npmjs.com/package/sequelize-auto-migrations

使用sequelize-cli,使用

sequelize init

创建您的模型并将其放在您的模型文件夹中。

安装sequelize-auto-migrations:

npm install sequelize-auto-migrations

使用以下命令创建初始迁移文件

node ./node_modules/sequelize-auto-migrations/bin/makemigration --name <initial_migration_name>

运行迁移:

node ./node_modules/sequelize-auto-migrations/bin/runmigration

您也可以从现有数据库自动生成模型,但这超出了问题的范围。



请注意,这不会生成向下迁移。
Thierry J.

1
这对我也不起作用。它使用我的表名生成一个迁移文件,仅此而已:没有列,没有模式,nada。
卡莱斯·阿尔科里亚

@CarlesAlcolea我的猜测是您的模型有问题。请发布一个单独的问题。
Kallaste

7

我创建了一个小型的“迁移文件生成器”。它使用创建的文件可以正常工作sequelize db:migrate-即使使用外键!

您可以在这里找到它:https : //gist.github.com/manuelbieh/ae3b028286db10770c81

我在包含12种不同模型的应用程序中对其进行了测试:

  • STRING,TEXT,ENUM,INTEGER,BOOLEAN,FLOAT作为数据类型

  • 外键约束(甚至是互惠的(用户属于所有者,团队属于用户作为所有者))

  • 使用索引namemethod以及unique性能


3
只是为了给尝试该脚本的任何人注意,它严格来说是针对mysql的
-Dakusan

我该如何运行?
CodeTrooper

2

尽管它不会自动生成,但是一种基于模型更改生成新迁移的方法是:(假设您使用的是迁移和模型处于同一级别的常规sequelize-cli文件结构)

  1. (与Manuel Bieh的建议相同,但是使用require而不是import)在您的迁移文件中(如果您没有迁移文件,则可以通过执行“ sequelize migration:create”生成一个),其代码如下:

    'use strict';
    var models = require("../models/index.js")
    module.exports = {
      up: function(queryInterface, Sequelize) {
        return queryInterface.createTable(models.User.tableName, 
          models.User.attributes);
      },
      down: function(queryInterface, Sequelize) {
        return queryInterface.dropTable('Users');
      }
    };
    
  2. 更改用户模型。

  3. 从数据库中删除表。
  4. 撤消所有迁移: sequelize db:migrate:undo:all
  5. 重新迁移以将更改保存在数据库中。 sequelize db:migrate

2
我认为您的代码做了类似的事情models.sequelize.sync({force: true})(只是稍微复杂一点)。如果更改模型,则无法更新架构,因为迁移已在运行(这就是您这样做的原因db:migrate:undo:all)。迁移应版本化您的数据库架构。这是一个很好的示例(我学到了很少的命令),但是我不会在中使用它production
czerasz

1
我同意,这消除了迁移的力量。当模型代码更改时会发生什么?迁移将具有不同的行为。迁移几乎应该像git commit一样读。拥有一个在特定时间点生成迁移的脚本真是太棒了,并且它可能会利用您在此处所做的事情。
Zeke Alexandre Nierenberg

您不应该使用drop撤消迁移。这与迁移数据的目的不符。如果撤消迁移,这将丢失所有用户数据,这不是迁移的目的。
Sebi2020 '19

2

截至2020年9月16日,这些答案中的大多数答案都不太一致!试试这个新的npm包

Sequelize-mig

它完成了sequelize-auto-migrations和其fork中的大多数已知问题,并对其进行了维护和记录!

它的使用方式类似于已知的

安装:

npm install sequelize-mig -g / yarn global add sequelize-mig

然后像这样使用它

sequelize-mig migration:make -n <migration name>

1

如果要与迁移一起创建模型,请使用以下命令:

sequelize model:create --name regions --attributes name:string,status:boolean --underscored

--underscored它用于创建具有下划线的列,例如:-created_at,updated_at或任何其他具有下划线的列,并支持用户定义的具有下划线的列。


-1

我最近尝试了以下方法,该方法似乎很好用,尽管我不确定100%是否可能有任何副作用:

'use strict';

import * as models from "../../models";

module.exports = {

  up: function (queryInterface, Sequelize) {

    return queryInterface.createTable(models.Role.tableName, models.Role.attributes)
    .then(() => queryInterface.createTable(models.Team.tableName, models.Team.attributes))
    .then(() => queryInterface.createTable(models.User.tableName, models.User.attributes))

  },

  down: function (queryInterface, Sequelize) {
    ...
  }

};

当使用进行上述迁移时sequelize db:migrate,我的控制台会说:

Starting 'db:migrate'...
Finished 'db:migrate' after 91 ms
== 20160113121833-create-tables: migrating =======
== 20160113121833-create-tables: migrated (0.518s)

所有的表都在那里,一切(至少似乎)都按预期工作。如果正确定义了它们,那么所有的关联都在那里。


2
我已经修改了上面的脚本,以为每个模型(在一个./tmp文件夹中)生成静态迁移文件:gist.github.com/manuelbieh/606710b003b5fe448100-正如我上面已经说过的:我不知道是否有任何负面影响,所以使用它慎用!
Manuel Bieh

您的模型目录是什么样的?您是否仍在使用sequelize建议的index.js脚本?
Trendsetter37 2016年

我收到[SyntaxError:意外的保留字]
user3631341

8
警告:这与整个迁移模型相反。如果只想每次从模型中创建表,则可以使用Sequelize的sync()函数。但是,它不能解决仅将字段添加到表中的升级生产服务器的问题。实现此目的的唯一方法是手动编写迁移。迁移依赖于以前运行的历史记录。仅进行一次迁移并用不同的模型每次重写都不会运行-因为SequelizeMeta表表明迁移之前已经在该服务器上运行。
Dor Rotman

3
此外,请设想一下这种情况:创建表迁移会从模型中创建所有表,就像它们在编译或构建安装包时所看到的一样。您部署服务器并在部署过程中运行迁移。稍后,您将创建仅添加字段的迁移。您升级服务器。一切正常。然后,您需要安装新服务器。该服务器将运行已经包含该字段的创建表迁移,然后运行仅添加字段的下一个迁移。由于该字段已经存在,因此第二次迁移将失败。结论:迁移永远不会改变。
Dor Rotman

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.