Sequelize.js:如何使用迁移和同步
我已经接近准备推出我的项目了。 我有大的计划,推出之后,数据库结构将发生变化 – 现有表中的新列以及新表,以及与现有和新模型的新关联。
我还没有触及Sequelize中的迁移,因为我只有testing数据,我不介意每次数据库更改时清除。
为此,目前我正在运行sync force: true
当我的应用程序启动时,如果我已经改变了模型定义,则为sync force: true
。 这将删除所有的表,并从头开始。 我可以省略force
选项,让它只创build新表。 但是,如果现有的改变,这是没有用的。
所以一旦我join迁移,事情是如何工作的? 显然,我不希望现有的表格(其中的数据)被清除,所以sync force: true
是不可能的。 在其他应用程序中,我已经帮助开发(Laravel和其他框架)作为应用程序部署过程的一部分,我们运行migrate命令来运行任何未决的迁移。 但是在这些应用程序中,第一次迁移有一个骨架数据库,数据库处于开发初期的一段时间 – 第一个alpha版本或其他。 因此,即使是晚会的应用程序的一个实例,也可以通过按顺序运行所有的迁移来一口气加速。
我如何在Sequelize中产生这样的“第一次迁移”? 如果我没有,那么应用程序的新实例将不会有骨架数据库来运行迁移,或者它将在开始时运行同步,并将使数据库处于新状态新的表格等等,但是当它试图运行迁移时,它们是没有意义的,因为它们是用原始数据库和每一个连续的迭代来logging的。
我的思考过程:在每个阶段,初始数据库加上每个迁移顺序应该等于(加或减数据)在sync force: true
运行时生成的数据库。 这是因为代码中的模型描述描述了数据库结构。 所以也许如果没有迁移表,我们只运行同步并将所有的迁移标记为已完成,即使它们没有运行。 这是我需要做什么(如何?),或者是Sequelize应该自己做这个,还是我咆哮错误的树? 如果我在正确的领域,肯定应该有一个很好的方式来自动生成大部分的迁移,给定旧模型(通过提交散列?甚至每个迁移可以绑定到一个提交?我承认我在想在一个不可移植的以git为中心的世界中)和新模型。 它可以对结构进行区分,并生成将数据库从旧到新的数据转换后所需的命令,然后开发人员可以进行必要的调整(删除/转换特定的数据等)。
当我用--init
命令运行sequelize二进制文件时,它给了我一个空的迁移目录。 当我然后运行sequelize --migrate
它使我没有任何内容的SequelizeMeta表,没有其他表。 显然不是,因为该二进制文件不知道如何引导我的应用程序并加载模型。
我肯定错过了什么。
TLDR:我如何设置我的应用程序及其迁移,以便实时应用程序的各种实例可以更新,以及没有传统启动数据库的全新应用程序?
生成“第一次迁移”
在你的情况下,最可靠的方法是几乎手动完成。 我会build议使用sequelize-cli工具。 语法很简单:
sequelize init ... sequelize model:create --name User --attributes first_name:string,last_name:string,bio:text
这将创build模型和迁移。 然后,手动合并现有的模型,并使用sequelize-cli生成模型,并使用迁移进行相同的操作。 完成后,擦除数据库(如果可能),然后运行
sequelize db:migrate
这将创build模式将迁移。 你只能这样做一次才能切换到适当的模式开发过程(没有同步:强制,但有权威的迁移)。
之后,当您需要更改模式时:
- 创build一个迁移:
sequelize migration:create
- 在你的迁移文件中写下你的function
- 根据您在迁移文件中的更改,手动更改模型
- 运行
sequelize db:migrate
在生产上运行迁移
显然,你不能ssh到生产服务器,并手动运行迁移。 使用umzug , Node.JS的框架不可知的迁移工具在应用程序启动之前执行未完成的迁移。
你可以得到一个待处理/尚未执行的迁移列表,如下所示:
umzug.pending().then(function (migrations) { // "migrations" will be an Array with the names of // pending migrations. });
然后执行迁移( 在callback中 )。 execute方法是一个通用函数,它为每个指定的迁移运行相应的函数:
umzug.execute({ migrations: ['some-id', 'some-other-id'], method: 'up' }).then(function (migrations) { // "migrations" will be an Array of all executed/reverted migrations. });
我的build议是在应用程序启动之前执行,并尝试每次服务路线。 像这样的东西:
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。
只是自己学习,但我想我会build议现在使用迁移,所以你习惯了他们。 我发现最好的办法是弄清楚迁移过程中发生的事情是看看由sequelize.sync()创build的表上的sql,然后从那里构build迁移。
迁移-c [迁移名称]
将在迁移目录中创build模板迁移文件。 然后,您可以填写您需要创build的字段。 这个文件需要包含createdAt / updatedAt,关联所需的字段等等。对于初始表的创build,应该有:
migration.dropTable( 'MyTable的');
但是对表结构的后续更新可以省去这个,只是使用alter table。
./node_modules/.bin/sequelize --migrate
创build示例如下所示:
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
这只是一个创buildfunction,它看起来像这样:
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/ 。 但基本的答案是你必须添加一切,以指定你需要的领域。 它不适合你:-(
对于开发 ,现在可以通过改变结构来同步当前表格。 使用来自sequelize github repo的最新版本,现在可以使用alter
参数运行同步。
Table.sync({alter: true})
来自文档的警告:
改变表格以适应模型。 不build议用于生产用途。 删除模型中已删除或其types已更改的列中的数据。
使用版本。 应用程序的版本取决于数据库的版本。 如果新版本需要更新数据库,请为其创build迁移。
更新:我决定放弃迁移( KISS ),并在需要时运行脚本update_db(sync forse:false)。
Sequelize可以运行任意SQL。 但要小心它是asynchronous的 。
我会做的是:
- 生成迁移(用作第一次迁移);
- 转储你的数据库,像这样:
mysql_dump -uUSER -pPASS DBNAME > FILE.SQL
- 将完整转储粘贴为文本(危险),或者使用Node中的完整转储加载文件:
-
var baseSQL = "LOTS OF SQL and it's EVIL because you gotta put \ backslashes before line breakes and \"quotes\" and/or sum" + " one string for each line, or everything will break";
-
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); } }
这应该照顾build立数据库,虽然asynchronous的事情可能成为一个问题。 如果发生这种情况,我会考虑延迟返回up
序列化函数,直到asynchronousquery
函数完成。
关于mysql_dump的更多信息: http ://dev.mysql.com/doc/refman/5.1/en/mysqldump.html
关于续集迁移的更多信息: http ://sequelize.readthedocs.org/en/latest/docs/migrations/
有关从Sequelize迁移中运行SQL的更多信息: https : //github.com/sequelize/sequelize/issues/313
现在用新的续集迁移非常简单。
这是你可以做的一个例子。
'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 }
在数据库configuration。
有点晚了,在阅读文档之后,你不需要首先进行迁移。 你所要做的就是调用sync
来创build表格。
sequelize.sync()
您也可以通过执行以下操作来运行简单的模型同步:
Project.sync()
但我认为sequelize.sync()
是您的项目更有用的一般情况下(只要您在开始时导入好模型)。
(取自http://sequelizejs.com/docs/latest/models#database-synchronization )
这将创build所有的初始结构。 之后,您将只需创build迁移以演变您的模式。
希望能帮助到你。
这是我目前的工作stream程。 我接受build议。
- 设置sequelize来创build不存在的表
- 设置sequelize删除并重新创build一个名为_blank的空白数据库中的所有表
- 使用mysql工具比较_blank和使用该工具同步更改。 仍然在寻找一个经济实惠的工具,可以在Mac上做到这一点。 MySql工作台看起来像您可以从现有模式导入模型,然后同步模式。 试图找出如何通过命令行来实现这一点。
这样,你不必手动更新迁移表,不必担心手指发胖,但你仍然得到一个ORM。
朋友我有同样的问题,并设法了解如何使用它们。
我开始没有ORM sequelize因此我已经有一个数据模型。
我必须使用sequelize-auto自动生成模型,并使用您创build的文件生成他们的迁移https://gist.github.com/ahelord/a7a7d293695b71aadf04157f0f7dee64并同步(; {Force: false}
)
这是dev.I将不得不版本的模型和迁移,并执行他们每次我拉代码。
在生产服务器只在楼上,所以你只需要运行迁移,并在每个提交pipe理,因为你将版本的模型,而不会停止后端