[database] Sequelize.js : 마이그레이션 및 동기화 사용 방법

프로젝트를 시작할 준비가되었습니다. 시작 후 큰 계획이 있으며 데이터베이스 구조가 변경됩니다. 기존 테이블의 새 열뿐만 아니라 새 테이블, 기존 및 새 모델에 대한 새로운 연결입니다.

Sequelize의 마이그레이션은 아직 다루지 않았습니다. 데이터베이스가 변경 될 때마다 데이터를 지우지 않아도되는 테스트 데이터 만 있었기 때문입니다.

이를 위해 현재 sync force: true모델 정의를 변경 한 경우 앱을 시작할 때 실행 중 입니다. 이렇게하면 모든 테이블이 삭제되고 처음부터 다시 만들어집니다. force새 테이블 만 만들 도록 옵션을 생략 할 수 있습니다. 그러나 기존 항목이 변경된 경우 유용하지 않습니다.

마이그레이션을 추가하면 어떻게 작동합니까? 분명히 기존 테이블 (데이터가있는)을 지우고 싶지 않기 때문에 문제가 아닙니다 sync force: true. 다른 앱에서 앱 배포 절차의 일부로 개발 (라 라벨 및 기타 프레임 워크)을 도왔습니다. 보류중인 마이그레이션을 실행하기 위해 migrate 명령을 실행합니다. 그러나 이러한 응용 프로그램에서 첫 번째 마이그레이션에는 기본 데이터베이스가 있으며, 데이터베이스는 개발 초기 시간 인 첫 번째 알파 릴리스 등의 상태에 있습니다. 따라서 파티 후반에 앱의 인스턴스조차도 모든 마이그레이션을 순서대로 실행하여 한 번에 속도를 높일 수 있습니다.

Sequelize에서 이러한 “첫 번째 마이그레이션”을 어떻게 생성합니까? 내가없는 경우 응용 프로그램의 새로운 인스턴스가 줄을 따라 마이그레이션을 실행할 골격 데이터베이스가 없거나 시작시 동기화를 실행하여 데이터베이스를 모두 새로운 상태로 만듭니다. 새 테이블 등이지만 마이그레이션을 실행하려고하면 원래 데이터베이스로 작성되고 각 연속 반복을 염두에두기 때문에 의미가 없습니다.

내 생각 과정 : 모든 단계에서 초기 데이터베이스와 각 마이그레이션 순서대로 데이터베이스가 생성 될 때 생성 된 데이터베이스와 동일해야합니다 (플러스 또는 마이너스 데이터) sync force: true실행됩니다. 코드의 모델 설명이 데이터베이스 구조를 설명하기 때문입니다. 따라서 마이그레이션 테이블이없는 경우 동기화를 실행하고 실행되지 않은 모든 마이그레이션을 완료로 표시합니다. 이것이 내가해야 할 일입니까 (어떻게?), Sequelize가 이것을 스스로해야합니까, 아니면 잘못된 나무를 짖고 있습니까? 그리고 내가 올바른 지역에 있다면, 구 모델 (커밋 해시로?) 또는 각 마이그레이션이 커밋에 묶여있을 수 있기 때문에 대부분의 마이그레이션을 자동으로 생성하는 좋은 방법이 있어야합니다. 이식 불가능한 자식 중심 우주에서) 및 새로운 모델. 그것은 구조를 구별하고 데이터베이스를 구식에서 신식으로 변환하는 데 필요한 명령을 생성 할 수 있으며 개발자는 들어가서 필요한 조정을 할 수 있습니다 (특정 데이터 삭제 / 전환 등).

--init명령으로 sequelize binary를 실행하면 빈 마이그레이션 디렉토리가 표시됩니다. 그런 다음 실행 sequelize --migrate하면 SequelizeMeta 테이블이 없어 다른 테이블이 없습니다. 바이너리는 내 앱을 부트 스트랩하고 모델을로드하는 방법을 모르기 때문에 분명히 아닙니다.

뭔가 빠졌을 것입니다.

TLDR : 레거시 시작 데이터베이스가없는 새로운 앱뿐만 아니라 다양한 라이브 앱 인스턴스를 최신 상태로 유지할 수 있도록 앱과 마이그레이션을 어떻게 설정합니까?



답변

“첫 번째 마이그레이션”생성

귀하의 경우 가장 신뢰할 수있는 방법은 거의 수동으로 수행하는 것입니다. 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하고 수동으로 마이그레이션을 실행할 수는 없습니다. umzug 사용 , 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를 수동으로 호출 할 필요가 없습니다.


답변

이것을 직접 배우는 것이지만 지금은 마이그레이션을 사용하는 것이 좋습니다. 마이그레이션에서 어떤 일이 발생하는지 알아내는 가장 좋은 방법은 테이블에서 SQL을보고 sequelize.sync()마이그레이션을 빌드하는 것입니다.

migrations -c [migration name] 

마이그레이션 디렉토리에 템플릿 마이그레이션 파일을 만듭니다. 그런 다음 필요한 필드로 채울 수 있습니다. 이 파일에는 createdAt/ updatedAt, 연관에 필요한 필드 등 이 포함되어야합니다 .

초기 테이블 생성을 위해서는 다음이 있어야합니다.

migration.dropTable('MyTable');

그러나 테이블 구조에 대한 후속 업데이트는 이것을 생략하고 alter table을 사용할 수 있습니다.

./node_modules/.bin/sequelize --migrate

create 예제는 다음과 같습니다.

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/ 에 있습니다. 그러나 기본적인 대답은 필요한 필드를 지정하기 위해 모든 것을 직접 추가해야한다는 것입니다. 그것은 당신을 위해하지 않습니다.


답변

들어 개발 , 이제 그 구조를 변경하여 현재 테이블을 동기화하는 옵션이 있습니다. sequelize github repo 의 최신 버전을 사용하여 이제 alter매개 변수 와 동기화를 실행할 수 있습니다 .

Table.sync({alter: true})

문서에서주의 사항 :

모델에 맞게 테이블을 변경합니다. 프로덕션 용도로는 권장되지 않습니다. 모델에서 제거되었거나 유형이 변경된 열의 데이터를 삭제합니다.


답변

이제 새로운 후행 마이그레이션으로 매우 간단합니다.

이것은 당신이 할 수있는 일의 예입니다.

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

데이터베이스 구성에서.


답변

버전을 사용하십시오. 응용 프로그램 버전은 데이터베이스 버전에 따라 다릅니다. 새 버전에 데이터베이스 업데이트가 필요한 경우 데이터베이스를 마이그레이션하십시오.

업데이트 : 마이그레이션을 포기하기로 결정하고 ( KISS ) 필요할 때 update_db 스크립트 (sync forse : false)를 실행 하기로 결정했습니다 .


답변

조금 늦었고 설명서를 읽은 후에는 처음 마이그레이션 할 필요가 없습니다. sync테이블을 만들려면 전화 하면됩니다.

sequelize.sync()

다음과 같은 작업을 수행하여 간단한 모델 동기화를 실행할 수도 있습니다.

Project.sync()하지만 sequelize.sync()좋은 시작 모델을 가져 오는 한 프로젝트에 더 유용한 경우 라고 생각합니다 .

( http://sequelizejs.com/docs/latest/models#database-synchronization 에서 가져옴 )

이것은 모든 초기 구조 를 만듭니다 . 이후에는 스키마를 발전시키기 위해 마이그레이션 만 작성하면됩니다.

도움이되기를 바랍니다.


답변

Sequelize는 임의의 SQL을 비동기 적으로 실행할 수 있습니다 .

내가 할 일은 :

  • 마이그레이션 생성 (첫 번째 마이그레이션으로 사용)
  • 다음과 같은 데이터베이스를 덤프하십시오. mysql_dump -uUSER -pPASS DBNAME > FILE.SQL
  • 전체 덤프를 텍스트로 붙여 넣거나 (위험한) 노드에 전체 덤프가있는 파일을로드하십시오.
    • 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 마이그레이션에 대한 : http://sequelize.readthedocs.org/en/latest/docs/migrations/
상세 정보 Sequelize Migration 내에서 SQL 실행 : https://github.com/sequelize/sequelize/issues/313