Sequelize.js: 移行と同期の使用方法 質問する

Sequelize.js: 移行と同期の使用方法 質問する

プロジェクトの立ち上げ準備がほぼ整いました。立ち上げ後には大きな計画があり、データベース構造が変更される予定です。既存のテーブルに新しい列や新しいテーブルが追加され、既存および新しいモデルへの新しい関連付けも追加されます。

データベースが変更されるたびに消去してもかまわないテスト データしか持っていないため、Sequelize での移行にはまだ触れていません。

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?

ベストアンサー1

Generating the "first migration"

あなたの場合、最も信頼できる方法は、ほぼ手動で行うことです。sequelize-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 回だけ実行する必要があります。

後でスキーマを変更する必要がある場合:

  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月

1年経ってもまだ役に立つので、現在のヒントを共有します。今のところ、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 を手動で呼び出す必要はありません。

おすすめ記事