web-dev-qa-db-ja.com

Sequelize.js:移行と同期の使用方法

私は自分のプロジェクトを立ち上げる準備ができているところです。ローンチ後の大きな計画があり、データベース構造が変更されます-既存のテーブルの新しい列、新しいテーブル、既存および新しいモデルへの新しい関連付け。

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

そのため、現在、モデル定義を変更した場合、アプリの起動時にsync force: trueを実行しています。これにより、すべてのテーブルが削除され、ゼロから作成されます。 forceオプションを省略して、新しいテーブルのみを作成できます。しかし、既存のものが変更された場合、これは役に立ちません。

移行に追加すると、どのように機能しますか?明らかに、既存のテーブル(データが含まれる)を消去したくないので、sync force: trueは問題外です。アプリの展開手順の一部として、私が開発を支援した他のアプリ(Laravelおよび他のフレームワーク)では、migrateコマンドを実行して保留中の移行を実行します。しかし、これらのアプリでは、最初の移行にはスケルトンデータベースがあり、データベースは開発のかなり早い時期の状態(最初のアルファリリースなど)にあります。そのため、パーティーに遅れたアプリのインスタンスでも、すべての移行を順番に実行することで、一度に速度を上げることができます。

Sequelizeでこのような「最初の移行」を生成するにはどうすればよいですか?持っていない場合、アプリの新しいインスタンスには、移行を実行するスケルトンデータベースがないか、開始時に同期が実行され、データベースがすべての新しい状態になります新しいテーブルなどがありますが、移行を実行しようとすると、意味がありません。元のデータベースと各反復を念頭に置いて記述されているためです。

私の思考プロセス:すべての段階で、初期データベースと各移行の順序は、sync force: trueの実行時に生成されるデータベースと同じ(プラスまたはマイナスのデータ)である必要があります。これは、コード内のモデルの説明がデータベース構造を説明しているためです。そのため、移行テーブルがない場合は、同期が実行され、すべての移行が実行されていなくても、完了としてマークされるだけです。これは私がする必要があるものですか(方法?)、またはSequelizeがこれを行うことになっていますか、それとも間違ったツリーをbarえていますか?そして、適切な領域にいる場合、古いモデル(コミットハッシュによるか、または各マイグレーションをコミットに結び付けることができますか?)移植性のないgit中心の宇宙で)と新しいモデル。構造を比較し、データベースを古いものから新しいものに変換したり戻したりするために必要なコマンドを生成できます。その後、開発者は必要な調整(特定のデータの削除/遷移など)を行うことができます。

--initコマンドでsequelizeバイナリを実行すると、空の移行ディレクトリが表示されます。次にsequelize --migrateを実行すると、SequelizeMetaテーブルが作成され、他のテーブルは含まれません。当然のことながら、そのバイナリはアプリをbootstrapする方法とモデルをロードする方法を知らないためです。

私は何かが欠けているに違いない。

TLDR:ライブアプリのさまざまなインスタンスを最新の状態に戻すことができるように、アプリとその移行をセットアップする方法、およびレガシー開始データベースのないまったく新しいアプリ

124
tremby

「最初の移行」の生成

あなたの場合、最も信頼できる方法はほとんど手動で行うことです。 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. 移行を作成します:sequelize migration:create
  2. 移行ファイルに関数を上下に書きます
  3. 移行ファイルの変更に応じて、モデルを手動で変更します
  4. sequelize db:migrateを実行します

本番環境での移行の実行

明らかに、実稼働サーバーにSSH接続して、手動で移行を実行することはできません。 mzug 、Node.JSのフレームワークに依存しない移行ツールを使用して、アプリの起動前に保留中の移行を実行します。

次のような保留中/未実行の移行のリストを取得できます。

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

次に、マイグレーションを実行します(inside 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.
});

そして、私の提案は、アプリが起動し、毎回ルートを提供しようとする前にそれを行うことです。このようなもの:

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

私は今これを試すことはできませんが、最初はそれが動作するはずです。

2016年4月更新

1年経ってもまだ有用なので、現在のヒントを共有してください。現時点では、必要に応じて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を手動で呼び出す必要はありません。

78
f1nn

これを自分で学習するだけですが、すぐに移行を使用することをお勧めします。移行で何が起こるかを理解するための最良の方法は、sequelize.sync()によって作成されたテーブルのsqlを見て、そこから移行をビルドすることです。

移行-c [移行名]

移行ディレクトリにテンプレート移行ファイルを作成します。その後、作成する必要のあるフィールドを入力できます。このファイルには、createdAt/updatedAt、アソシエーションに必要なフィールドなどを含める必要があります。最初のテーブル作成には、次のものが必要です。

migration.dropTable( 'MyTable');

ただし、その後のテーブル構造の更新ではこれを省略し、alter tableを使用するだけです。

./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: '[email protected]'
.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/ にあります。ただし、基本的な答えは、必要なフィールドを指定するにはすべてを自分で追加する必要があるということです。それはあなたのためにそれをしません:-(

16
user1916988

developmentには、構造を変更して現在のテーブルを同期するオプションがあります。 sequelize github repo の最新バージョンを使用して、alterパラメーターで同期を実行できるようになりました。

Table.sync({alter: true})

ドキュメントからの注意:

モデルに合わせてテーブルを変更します。実稼働環境での使用は推奨されていません。モデルで削除されたか、タイプが変更された列のデータを削除します。

11
meyer9

現在、新しいsequelizeの移行は非常に簡単です。

これはあなたができることの例です。

    '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 }

データベース構成上。

3

Sequelizeは任意のSQLを非同期的に実行できます

私がやることは:

  • 移行の生成(最初の移行として使用するため);
  • 次のようなデータベースをダンプします: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 Migrationでこのダンプを実行します。
module.exports = {
  up: function (migration, DataTypes) {
    var baseSQL = "whatever" // I recommend loading a file
    migration.migrator.sequelize.query(baseSQL);
  }
}

非同期の問題が発生する可能性はありますが、データベースのセットアップは注意してください。その場合は、非同期up関数が終了するまで、query sequelize関数の返送を延期する方法を検討します。

Mysql_dumpの詳細: http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html
Sequelize Migrationsの詳細: http://sequelize.readthedocs.org/en/latest/docs/migrations/
Sequelize Migration内からのSQLの実行の詳細: https://github.com/sequelize/sequelize/issues/31

2

少し遅れて、ドキュメントを読んだ後、あなたが話している最初の移行をする必要はありません。テーブルを作成するには、syncを呼び出すだけです。

sequelize.sync()

次のようなことで、単純なモデル同期を実行することもできます。

Project.sync()しかし、私はsequelize.sync()があなたのプロジェクトにとってより有用な一般的なケースだと思います(開始時に良いモデルをインポートする限り)。

http://sequelizejs.com/docs/latest/models#database-synchronization から取得)

これにより、すべてのinitial構造が作成されます。その後、スキーマを進化させるために移行を作成するだけで済みます。

それが役に立てば幸い。

2
kiddouk

バージョンを使用します。アプリケーションのバージョンは、データベースのバージョンに依存します。新しいバージョンでデータベースの更新が必要な場合は、そのための移行を作成します。

更新:移行を中止し( KISS )、必要なときにスクリプトupdate_db(sync forse:false)を実行することにしました。

2
ahiipsa

友人私も同じ質問をして、どうやってそれらを使うかを理解できました。

ORM sequelizeなしで始めたので、すでにデータモデルがありました。
sequelize-autoを使用してモデルを自動的に生成し、作成したこのファイルを使用して移行を生成する必要がありました https://Gist.github.com/ahelord/a7a7d293695b71aadf04157f0f7dee64{Force: false}
これはdevにあります。コードをプルするたびにモデルと移行をバージョン管理し、実行する必要があります。

実稼働環境では、サーバーは2階にあるため、移行を実行するだけで、バックエンドを停止せずにモデルをバージョン管理するため、各コミットで管理するだけです。

1

さらに簡単な方法があります(Sequalizeを回避する)。これは次のようになります:

  1. プロジェクト内にコマンドを入力します:npm run migrate:new

  2. これにより、3つのファイルが作成されます。 jsファイル、およびupおよびdownという名前の2つのsqlファイル

  3. これらのファイルにSQLステートメントを入れます。これは純粋なsqlです
  4. 次に入力します:npm run migrate:upまたはnpm run migrate:down

これが機能するためには、 db-migrate モジュールをご覧ください。

セットアップが完了したら(難しいことではありません)、DBの変更は本当に簡単で、時間を大幅に節約できます。

0

これが私の現在のワークフローです。私は提案を受け入れます。

  1. Sequelizeを設定して、存在しないテーブルを作成します
  2. Sequelizeを設定して、_blankという名前の空のデータベースにすべてのテーブルをドロップして再作成します。
  3. Mysqlツールを使用して_blankを比較し、そのツールを使用して変更を同期します。 Macでこれを実行できる手頃な価格のツールを探しています。 MySqlワークベンチは、既存のスキーマからモデルをインポートし、スキーマを同期できるように見えます。簡単にするために、コマンドラインを介してこれを行う方法を理解しようとしています。

そうすれば、移行テーブルを手動で更新する必要がなく、太った指を心配する必要がありませんが、それでもORMを取得できます。

0
TWilly