我快要准备好启动我的项目了。我对发布后有很大的计划,数据库结构将发生变化——现有表中的新列以及新表,以及与现有模型和新模型的新关联。

我还没有接触 Sequelize 中的迁移,因为我只有测试数据,我不介意每次数据库更改时都将其删除。

为此,目前我正在运行 sync force: true 当我的应用程序启动时,如果我更改了模型定义。这将删除所有表并从头开始创建它们。我可以省略 force 选项,让它只创建新表。但是如果现有的已经改变,这没有用。

所以一旦我添加了迁移,事情是如何运作的?显然我不希望现有的表(其中有数据)被清除,所以 sync force: true 是不可能的。在我帮助开发的其他应用程序(Laravel 和其他框架)上,作为应用程序部署过程的一部分,我们运行 migrate 命令来运行任何挂起的迁移。但是在这些应用程序中,第一次迁移有一个骨架数据库,数据库处于开发早期的状态——第一个 alpha 版本或其他。因此,即使是聚会迟到的应用程序实例,也可以通过按顺序运行所有迁移,一次性加快速度。

如何在 Sequelize 中生成这样的“第一次迁移”?如果我没有,那么应用程序的某个新实例将没有框架数据库来运行迁移,或者它将在开始时运行同步并使数据库处于新状态新表等,但是当它尝试运行迁移时,它们将没有意义,因为它们是用原始数据库和每次连续迭代编写的。

我的思考过程:在每个阶段,初始数据库加上顺序的每次迁移应该等于(加或减数据)运行sync force: true时生成的数据库。这是因为代码中的模型描述描述了数据库结构。所以也许如果没有迁移表,我们只是运行同步并将所有迁移标记为完成,即使它们没有运行。这是我需要做的(怎么做?),还是 Sequelize 应该自己做这件事,还是我在找错树?如果我在正确的区域,肯定应该有一个很好的方法来自动生成大部分迁移,考虑到旧模型(通过提交哈希?甚至每个迁移都可以与提交相关联吗?我承认我在想在以 git 为中心的非便携式宇宙中)和新模型。它可以区分结构并生成将数据库从旧数据库转换为新数据库并返回所需的命令,然后开发人员可以进行任何必要的调整(删除/转换特定数据等)。

当我使用 --init 命令运行 sequelize 二进制文件时,它给了我一个空的迁移目录。然后当我运行 sequelize --migrate 时,它使我成为一个 SequelizeMeta 表,里面没有任何内容,没有其他表。显然不是,因为那个二进制文件不知道如何引导我的应用程序并加载模型。

我肯定错过了什么。

TLDR:我如何设置我的应用程序及其迁移,以便实时应用程序的各种实例可以更新,以及一个没有遗留起始数据库的全新应用程序?

最佳答案

生成“第一次迁移”

在您的情况下,最可靠的方法是几乎手动完成。我建议使用 sequelize-cli 工具。语法相当简单:

sequelize init
...
sequelize model:create --name User --attributes first_name:string,last_name:string,bio:text

这将创建模型和迁移。然后,手动将现有模型与使用 sequelize-cli 生成的模型合并,并对迁移执行相同操作。执行此操作后,删除数据库(如果可能),然后运行
sequelize db:migrate

这将创建架构将迁移。您应该只执行一次以切换到模式开发的正确过程(没有同步:强制,但有权威的迁移)。

稍后,当您需要更改架构时:
  • 创建迁移:sequelize migration:create
  • 在迁移文件中写入向上和向下函数
  • 根据你迁移文件的变化,手动修改你的模型
  • 运行 sequelize db:migrate

  • 在生产中运行迁移

    显然,您无法通过 ssh 连接到生产服务器并手动运行迁移。使用 umzug ,Node.JS 的框架不可知迁移工具在应用程序启动之前执行挂起的迁移。

    您可以获得一个挂起/尚未执行的迁移列表,如下所示:
    umzug.pending().then(function (migrations) {
      // "migrations" will be an Array with the names of
      // pending migrations.
    });
    

    然后执行迁移(回调 内的 )。 execute 方法是一个通用函数,它为每个指定的迁移运行相应的函数:
    umzug.execute({
      migrations: ['some-id', 'some-other-id'],
      method: 'up'
    }).then(function (migrations) {
      // "migrations" will be an Array of all executed/reverted migrations.
    });
    

    我的建议是在应用程序启动之前执行此操作,并尝试每次都提供路由。像这样的东西:
    umzug.pending().then(function(migrations) {
        // "migrations" will be an Array with the names of
        // pending migrations.
        umzug.execute({
            migrations: migrations,
            method: 'up'
        }).then(function(migrations) {
            // "migrations" will be an Array of all executed/reverted migrations.
            // start the server
            app.listen(3000);
            // do your stuff
        });
    });
    

    我现在不能尝试这个,但乍一看它应该可以工作。

    UPD 2016 年 4 月

    一年后,仍然有用,所以分享我目前的技巧。现在,我正在根据需要安装 sequelize-cli live 依赖项,然后像这样修改 package.json 中的 NPM 启动脚本:
    ...
    "scripts": {
      "dev": "grunt && sequelize db:migrate && sequelize db:seed:all && node bin/www",
      "start": "sequelize db:migrate && sequelize db:seed:all && node bin/www"
    },
    ...
    

    我唯一需要在生产服务器上做的是 npm start 。此命令将运行所有迁移,应用所有播种机并启动应用服务器。无需手动调用 umzug。

    关于database - Sequelize.js:如何使用迁移和同步,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21105748/

    10-16 18:05