Sequelize.js:如何使用迁移和同步 [英] Sequelize.js: how to use migrations and sync

查看:3777
本文介绍了Sequelize.js:如何使用迁移和同步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我接近我的项目准备发布。我有很大的计划,推出后,数据库结构将改变 - 现有表中的新列以及新表,以及新的关联到现有的和新的模型。



我还没有碰到Sequelize中的迁移,因为我只有测试数据,我不介意抹去每次数据库更改。



结束,目前我运行同步力:真当我的应用程序启动,如果我改变了模型定义。这将删除所有表,并从头开始。我可以省略 force 选项,让它只创建新表。但是,如果现有的改变了,这是没有用的。



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



如何生成这样的第一迁移在Sequelize?如果我没有一个,应用程序的一个新的实例在某种程度上将没有骨架数据库运行迁移,或者它将在运行同步开始,将使数据库处于新的状态与所有新表等,但是当它试图运行迁移时,他们将是没有意义的,因为它们是用原始数据库和每个连续迭代写的。



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



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



我必须缺少的东西。



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

解决方案

生成第一个迁移



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

  sequelize init 
...
sequelize模型:create --name用户--attributes first_name:string,last_name:string,bio:text

移民。然后,手动合并现有模型与sequ​​elize-cli生成的模型,并对migrations执行相同操作。完成后,擦除数据库(如果可能),然后运行

  sequelize db:migrate 

这将创建模式迁移。你应该这样做只有一次,以切换到正确的模式开发过程(没有sync:force,但是有权威的迁移)。



后来,当你需要改变模式:


  1. 创建迁移: sequelize migration:create

  2. 在迁移文件中写入和删除函数

  3. 根据迁移文件中的更改,手动更改模型

  4. 运行 sequelize db:migrate



在生产上运行迁移



显然,你不能ssh到生产服务器和手动运行迁移。使用 umzug (用于Node.JS的框架无关的迁移工具)在应用启动之前执行待执行的迁移。



您可以获得挂起/尚未执行的迁移列表,如下所示:

  umzug.pending()。then(function(migrations){
//migrations将是一个名为
的数组//正在迁移
});

然后执行迁移( inside callback )。 execute方法是一个通用函数,为每个指定的迁移运行相应的函数:

  umzug.execute({
migrations:['some-id','some-other-id'],
method:'up'
} 将是所有已执行/恢复的迁移的数组。
});

我的建议是在应用程序启动前尝试每次都为路由服务。这样的东西:

  umzug.pending()。then(function(migrations){
//migrations将会是一个名为
//待处理迁移的数组。
umzug.execute({
migrations:migrations,
method:'up'
})。那么(function(migrations){
//migrations将是所有已执行/恢复的迁移的数组
//启动服务器
app.listen(3000);
// do your stuff
});
});

我现在无法试试,但首先看看它应该可以工作。



UPD 2016年4月



一年后,仍然有用,因此分享我目前的提示。现在,我根据需要安装 sequelize-cli 生效依赖,然后修改包中的NPM启动脚本.json ,如下所示:

  ... 
scripts:{
dev:grunt&& sequelize db:migrate&&& sequelize db:seed:all&&&  bin / www,
start:sequelize db:migrate& ;& sequelize db:seed:all&&&&&&&&&&&>

我需要在生产服务器上做的只有 npm start 。此命令将运行所有迁移,应用所有种子和启动应用程序服务器。无需手动调用umzug。


I'm close to having my project ready to launch. I have big plans for after launch and the database structure is going to change -- new columns in existing tables as well as new tables, and new associations to existing and new models.

I haven't touched migrations in Sequelize yet, since I've only had testing data which I don't mind wiping out every time the database changes.

To that end, at present I'm running sync force: true when my app starts up, if I have changed the model definitions. This deletes all the tables and makes them from scratch. I could omit the force option to have it only create new tables. But if existing ones have changed this is not useful.

So once I add in migrations how do things work? Obviously I don't want existing tables (with data in them) to be wiped out, so sync force: true is out of the question. On other apps I've helped develop (Laravel and other frameworks) as part of the app's deployment procedure we run the migrate command to run any pending migrations. But in these apps the very first migration has a skeleton database, with the database in the state where it was some time early in development -- the first alpha release or whatever. So even an instance of the app late to the party can get up to speed in one go, by running all migrations in sequence.

How do I generate such a "first migration" in Sequelize? If I don't have one, a new instance of the app some way down the line will either have no skeleton database to run the migrations on, or it will run sync at the start and will make the database in the new state with all the new tables etc, but then when it tries to run the migrations they won't make sense, since they were written with the original database and each successive iteration in mind.

My thought process: at every stage, the initial database plus each migration in sequence should equal (plus or minus data) the database generated when sync force: true is run. This is because the model descriptions in the code describe the database structure. So maybe if there is no migration table we just run sync and mark all the migrations as done, even though they weren't run. Is this what I need to do (how?), or is Sequelize supposed to do this itself, or am I barking up the wrong tree? And if I'm in the right area, surely there should be a nice way to auto generate most of a migration, given the old models (by commit hash? or even could each migration be tied to a commit? I concede I am thinking in a non-portable git-centric universe) and the new models. It can diff the structure and generate the commands needed to transform the database from old to new, and back, and then the developer can go in and make any necessary tweaks (deleting/transitioning particular data etc).

When I run the sequelize binary with the --init command it gives me an empty migrations directory. When I then run sequelize --migrate it makes me a SequelizeMeta table with nothing in it, no other tables. Obviously not, because that binary doesn't know how to bootstrap my app and load the models.

I must be missing something.

TLDR: how do I set up my app and its migrations so various instances of the live app can be brought up to date, as well as a brand new app with no legacy starting database?

解决方案

Generating the "first migration"

In your case, the most reliable way is to do it almost manually. I would suggest to use sequelize-cli tool. The syntax is rather plain:

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

This will create both model AND migration. Then, manually merge your existing models with generated with sequelize-cli, and do the same with migrations. After doing this, wipe database (if possible), and run

sequelize db:migrate

This will create schema will migrations. You should do this only once to switch to proper process of schema developments (without sync:force, but with authoritative migrations).

Later, when you need to change schema:

  1. Create a migration: sequelize migration:create
  2. Write up and down functions in your migration file
  3. According to your changes in migration file, change your model manually
  4. Run sequelize db:migrate

Running migrations on production

Obviously you can't ssh to production server and run migrations by hands. Use umzug, framework agnostic migration tool for Node.JS to perform pending migrations before app starts.

You can get a list of pending/not yet executed migrations like this:

umzug.pending().then(function (migrations) {
  // "migrations" will be an Array with the names of
  // pending migrations.
}); 

Then execute migrations (inside callback). The execute method is a general purpose function that runs for every specified migrations the respective function:

umzug.execute({
  migrations: ['some-id', 'some-other-id'],
  method: 'up'
}).then(function (migrations) {
  // "migrations" will be an Array of all executed/reverted migrations.
});

And my suggestion is to do it before app starts and tries to serve routes every time. Something like this:

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
    });
});

I can't try this right now, but at first look it should work.

UPD Apr. 2016

After a year, still useful, so sharing my current tips. For now, I'm installing sequelize-cli package as required live dependancy, and then modify NPM startup scripts in package.json like this:

...
"scripts": {
  "dev": "grunt && sequelize db:migrate && sequelize db:seed:all && node bin/www",
  "start": "sequelize db:migrate && sequelize db:seed:all && node bin/www"
},
...

The only thing I need to do on production server is npm start. This command will run all migrations, apply all seeders and start app server. No need to call umzug manually.

这篇关于Sequelize.js:如何使用迁移和同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆