Sequelize.js: 如何使用 migrations 和 sync

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

我还没有涉及到 Sequelize 的迁移,因为我只有测试数据,我不介意每次数据库改变的时候删除这些数据。

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

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

我如何在 Sequelize 产生这样的“首次移民”?如果我没有一个,一个新的应用程序实例或者没有骨架数据库来运行迁移,或者它会在开始运行同步,使数据库处于新的状态,包含所有新的表等等,但是当它尝试运行迁移时,它们就没有意义了,因为它们是根据原始数据库和每个连续的迭代编写的。

我的思考过程是: 在每个阶段,初始数据库加上按顺序进行的每次迁移应该等于运行 sync force: true时生成的数据库(正负数据)。这是因为代码中的模型描述描述了数据库结构。因此,如果没有迁移表,我们可能只需要运行 sync,并将所有迁移标记为已完成,即使它们没有运行。这是我需要做的吗(怎么做?)还是应该由 Sequelize 自己来做,还是我找错人了?如果我在正确的地方,肯定有一个很好的方法来自动生成大部分迁移,给定的旧模型(提交散列?或者甚至可以将每次迁移都绑定到一个提交上?我承认我正在思考一个不可移植的以 git 为中心的世界)和新模型。它可以区分结构并生成将数据库从旧数据库转换为新数据库以及从新数据库转换回数据库所需的命令,然后开发人员可以进行任何必要的调整(删除/转换特定数据等)。

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

我肯定漏掉了什么。

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

91566 次浏览

我自己刚刚学到这一点,但是我建议您现在就使用迁移,以便您能够习惯它们。我发现,要弄清楚迁移过程中发生了什么,最好的办法是查看由 sequelize.sync()创建的表上的 sql,然后从那里构建迁移。

migrations -c [migration name]

将在迁移目录中创建模板迁移文件。然后可以用需要创建的字段填充它。这个文件需要包含 createdAt/updatedAt、关联所需的字段等。

对于初始表的创建,向下应该有:

migration.dropTable('MyTable');

但是对表结构的后续更新可以忽略这一点,只使用 alter 表。

./node_modules/.bin/sequelize --migrate

创建的示例如下:

module.exports = {
up: function(migration, DataTypes, done) {
migration.createTable(
'MyTable',
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
bigString: {type: DataTypes.TEXT, allowNull: false},
MyOtherTableId: DataTypes.INTEGER,
createdAt: {
type: DataTypes.DATE
},
updatedAt: {
type: DataTypes.DATE
}
});
done();
},
down: function(migration, DataTypes, done) {
migration.dropTable('MyTable');
done();
}

从头重做:

./node_modules/.bin/sequelize --migrate --undo
./node_modules/.bin/sequelize --migrate

我用咖啡来运行种子文件来填充表格:

coffee server/seed.coffee

这里只有一个 create 函数,看起来像这样:

user = db.User.create
username: 'bob'
password: 'suruncle'
email: 'bob@bob.com'
.success (user) ->
console.log 'added user'
user_id = user.id
myTable = [
field1: 'womp'
field2: 'rat'


subModel: [
field1: 'womp'
,
field1: 'rat'
]
]

记住将 sync()从模型的索引中移除,否则它将覆盖迁移和种子所做的工作。

医生当然在 http://sequelize.readthedocs.org/en/latest/docs/migrations/。但基本的答案是,您必须在自己中添加所有内容,以指定所需的字段。这对你没用。

使用版本。 应用程序的版本取决于数据库的版本。 如果新版本需要更新数据库,请为其创建迁移。

Update: 我决定放弃迁移(亲一个) ,在需要时运行 script update _ db (sync forse: false)。

有点晚了,在阅读了文档之后,您不需要进行您所说的第一次迁移。您所要做的就是调用 sync来创建表。

sequelize.sync()

您还可以执行以下操作来运行一个简单的模型同步:

但是我认为 sequelize.sync()对于您的项目来说是一个更有用的通用案例(只要您在开始时导入好的模型)。

(摘自 http://sequelizejs.com/docs/latest/models#database-synchronization)

这将创建所有的 首字母缩写结构。

希望能有所帮助。

Sequelize 可以运行任意的 SQL异步的

我要做的是:

  • 生成迁移(用作第一次迁移) ;
  • 转储数据库,比如: mysql_dump -uUSER -pPASS DBNAME > FILE.SQL
  • 要么将完整转储粘贴为文本(危险) ,要么在 Node 中加载具有完整转储的文件:
    • Var baseSQL = “ LOTS OF SQL and it’s EVIL because you got ta put 在换行符和“引号”和/或“和”+ 之前加上反斜杠 “每行一个字符串,否则一切都会中断”;
    • var baseSQL = fs.readFileSync('../seed/baseDump.sql');
  • 在 Sequelize 迁移上运行这个转储:
module.exports = {
up: function (migration, DataTypes) {
var baseSQL = "whatever" // I recommend loading a file
migration.migrator.sequelize.query(baseSQL);
}
}

这应该可以解决设置数据库的问题,尽管异步可能会成为一个问题。如果发生这种情况,我将研究一种方法,将返回 up序列化函数的时间推迟到异步 query函数完成之后。

更多关于 mysql _ dump: http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html
更多关于 Sequelize 偏移的信息: < a href = “ http://Sequelize.readthedocs.org/en/update/docs/mobilations/”rel = “ nofollow norefrer”> http://Sequelize.readthedocs.org/en/latest/docs/Migrations/
更多关于在 Sequelize mobile 中运行 SQL 的内容: < a href = “ https://github.com/Sequelize/Sequelize/questions/313”rel = “ nofollow norefrer”> https://github.com/Sequelize/Sequelize/issues/313

生成“第一次迁移”

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

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

这将创建模型和迁移。然后,手动将现有模型与 Sequelize-cli 生成的模型合并,并对迁移执行同样的操作。完成此操作后,擦除数据库(如果可能) ,然后运行

sequelize db:migrate

这将创建模式将迁移。为了切换到模式开发的正确过程(不使用 sync: force,但使用权威的迁移) ,您应该只执行一次此操作。

稍后,当您需要更改模式时:

  1. 创建迁移: sequelize migration:create
  2. 在迁移文件中写入向上和向下函数
  3. 根据迁移文件中的更改,手动更改模型
  4. 运行 sequelize db:migrate

在生产环境中运行迁移

显然,您不能 ssh 到生产服务器并手动运行迁移。在应用程序启动之前,使用 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包,然后像下面这样修改 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。

现在用新的序列化迁移非常简单。

这是你能做的一个例子。

    'use strict';


var Promise = require('bluebird'),
fs = require('fs');


module.exports = {
up: function (queryInterface, Sequelize) {


return Promise
.resolve()
.then(function() {
return fs.readFileSync(__dirname + '/../initial-db.sql', 'utf-8');
})
.then(function (initialSchema) {
return queryInterface.sequelize.query(initialSchema);
})
},


down: function (queryInterface, Sequelize) {
return Promise
.resolve()
.then(function() {
return fs.readFileSync(__dirname + '/../drop-initial-db.sql', 'utf-8');
})
.then(function (dropSql) {
return queryInterface.sequelize.query(dropSql);
});
}
};

记住你必须设置:

"dialectOptions": { "multipleStatements": true }

在数据库配置上。

以下是我目前的工作流程,欢迎提出建议。

  1. 设置 Sequelize 以创建不存在的表
  2. 设置序列化 删除并重新创建空白数据库中的所有表 空白
  3. 使用 mysql 工具进行比较 _ space 和同步更改,使用 那个工具。仍然在寻找一个负担得起的工具,可以做到这一点 MySql 工作台看起来可以从 然后同步模式 通过命令行完成此操作,使其更加容易。

这样,您就不必手动更新迁移表,也不必担心手指太粗,但您仍然可以得到一个 ORM。

对于 发展,现在有一个通过改变当前表的结构来同步当前表的选项。使用 连续化 github 回购的最新版本,现在可以使用 alter参数运行 sync。

Table.sync({alter: true})

来自医生的警告:

更改表格以适应模型。不推荐用于生产用途。删除在模型中已删除或其类型已更改的列中的数据。

朋友,我有同样的问题,并设法理解如何使用它们。

我开始没有 ORM 序列化,因此我已经有了一个数据模型。
我必须使用 Sequelize-auto 自动生成模型,并使用您创建的 https://gist.github.com/ahelord/a7a7d293695b71aadf04157f0f7dee64和 sync ({Force: false})文件生成它们的迁移
这是在开发中,我必须对模型和迁移进行版本控制,并在每次提取代码时执行它们。

在生产环境中,服务器只在楼上运行,因此您只需要运行迁移,并且在每次提交管理中,您将在不停止后端的情况下对模型进行版本管理

还有一个更简单的方法(避免 Sequalize) ,它是这样的:

  1. 在项目中键入一个命令: Npm 运行迁移: 新的

  2. 这将创建3个文件。一个 js 文件和两个上下命名的 sql 文件

  3. 您将 SQL 语句放在这些文件中,它是纯 SQL
  4. 然后输入: Npm 运行迁移: 向上Npm 运行迁移: 向下

为了实现这一点,请看一下 Db- 迁移模块。

一旦设置好数据库(这并不困难) ,更改数据库就非常容易,而且节省了大量时间。

我看了这篇文章和类似的问题,它并没有真正回答我。迁移对于旋转本地数据库和在生产中更新数据非常有用

我在这里问了这个问题,也回答了它: 处理序列化迁移和初始化的工作流?

绿地模式的 TL-DR 版本

  1. 按照传统方式使用纯 SQL 脚本或者使用 GUI 工具来设计数据库模式
  2. 当您完成了95% 的 db 模式并且满意之后,可以继续移动它,通过移动整个 .sql文件来进行序列化
  3. 进行第一次迁移。在 models所在的任何文件夹中运行 sequelize init:migrate
  4. 创建第一个迁移文件。运行 sequelize migration:generate --name [name_of_your_migration]
  5. 在那个迁移文件中,把这段代码放进去
("use strict");
/**
* DROP SCHEMA public CASCADE; CREATE SCHEMA public
* ^ there's a schema file with all the tables in there. it drops all of that, recreates
*/
const fs = require("fs");
const initialSqlScript = fs.readFileSync("./migrations/sql/Production001.sql", {
encoding: "utf-8",
});
const db = require("../models");
module.exports = {
up: () => db.sequelize.query(initialSqlScript),
down: () =>
db.sequelize.query(`DROP SCHEMA public CASCADE; CREATE SCHEMA public;
`),
};

enter image description here

使用此常规文件夹结构

enter image description here

  1. 现在,序列化设置与初始数据库模式同步
  2. 当您想要编辑数据库模式时,再次运行 sequelize migration:generate --name [name_of_your_migration]
  3. 继续并在这里对 updown迁移路径进行修改。这些是用于更改列名、 DELETE、 ADD 列等的 ALTER 语句
  4. 运行 sequelize db:migrate
  5. 您希望模型与对远程数据库的更改同步,因此现在可以使用 npm install sequelize-auto
  6. 这将读取数据库上的当前数据库模式并自动生成模型文件。使用类似于 https://github.com/sequelize/sequelize-auto下的 sequelize-auto -o "./models" -d sequelize_auto_test -h localhost -u my_username -p 5432 -x my_password -e postgres命令

您可以使用 git 来查看模型上的分歧日志,应该只有反映数据库模型中的变化的更改。另外,如果您使用 sequelize auto,请不要直接修改 models,因为这将为您生成它们。同样,您不再需要直接使用 SQL 文件修改数据库模式,因为您可以导入这些 .sql文件

现在您的数据库模式是最新的,并且您已经正式转移到仅对数据库迁移进行序列化。

一切都是版本控制。这是数据库和后端开发的理想工作流程