Sequelize.js: как использовать миграции и синхронизацию

Я близок к тому, что мой проект готов к запуску. У меня есть большие планы после запуска, и структура базы данных изменится - новые столбцы в существующих таблицах, а также новые таблицы и новые ассоциации с существующими и новыми моделями.

Я еще не затронул миграцию в Sequelize, так как у меня только были данные тестирования, которые я не против уничтожать при каждом изменении базы данных.

С этой целью в настоящее время я запускаю sync force: true, когда мое приложение запускается, если я изменил определения модели. Это удаляет все таблицы и делает их с нуля. Я мог бы опустить параметр force, чтобы он создавал только новые таблицы. Но если существующие изменились, это не полезно.

Итак, как только я добавляю в миграцию, как все работает? Очевидно, что я не хочу, чтобы существующие таблицы (с данными в них) были уничтожены, поэтому sync force: true не может быть и речи. В других приложениях я помог разработать (Laravel и другие фреймворки) в рамках процедуры развертывания приложения, мы запускаем команду migrate для запуска любых ожидающих миграции. Но в этих приложениях первая миграция имеет скелетную базу данных с базой данных в состоянии, где было некоторое время на ранней стадии разработки - первой альфа-версии или что-то еще. Таким образом, даже экземпляр приложения с опозданием на вечеринку может ускориться за один раз, выполнив все миграции в последовательности.

Как создать такую ​​ "первую миграцию" в Sequelize? Если у меня его нет, новый экземпляр приложения каким-либо образом пойдет по строке либо не будет иметь базы данных скелета для запуска миграции, либо он будет запускать синхронизацию в начале и сделает базу данных в новом состоянии со всеми новые таблицы и т.д., но затем, когда он пытается запустить миграции, они не будут иметь смысла, поскольку они были написаны с исходной базой данных и каждой последовательной итерацией.

Мой мыслительный процесс: на каждом этапе исходная база данных плюс каждая миграция в последовательности должны быть равны (плюс или минус данные), сгенерированные при запуске sync force: true. Это связано с тем, что описания моделей в коде описывают структуру базы данных. Так что, возможно, если нет таблицы миграции, мы просто запускаем синхронизацию и отмечаем все миграции как выполненные, хотя они не были запущены. Это то, что мне нужно делать (как?), Или Sequelize, как предполагается, делать это сам, или я лаяю неправильное дерево? И если я нахожусь в правильной области, наверняка должен быть хороший способ автоматически генерировать большую часть миграции, учитывая старые модели (путем хеширования или даже привязать каждую миграцию к фиксации?) Я соглашаюсь, что я думаю в не-переносной git -центрической вселенной) и новых моделях. Он может различать структуру и генерировать команды, необходимые для преобразования базы данных из старой в новую и обратно, а затем разработчик может входить и делать любые необходимые настройки (удаление/переход определенных данных и т.д.).

Когда я запускаю сиквел-бинарный код с помощью команды --init, он дает мне пустой каталог миграции. Когда я запускаю sequelize --migrate, он делает мне таблицу SequelizeMeta, в которой нет ничего, никаких других таблиц. Очевидно, нет, потому что этот двоичный файл не знает, как загружать мое приложение и загружать модели.

Мне что-то не хватает.

TL;DR: как настроить мое приложение и его миграции, чтобы можно было обновить различные экземпляры live-приложения, а также совершенно новое приложение без старой исходной базы данных?

Ответ 1

Создание "первой миграции"

В вашем случае самый надежный способ - сделать это почти вручную. Я бы предложил использовать инструмент secelize-cli. Синтаксис довольно прост:

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

Это приведет к миграции как модели, так и миграции. Затем вручную объедините существующие модели сгенерированными с помощью sequelize-cli и сделайте то же самое с миграциями. После этого очистите базу данных (если возможно) и запустите

sequelize db:migrate

Это приведет к миграции схем. Вы должны сделать это только один раз, чтобы перейти к правильному процессу разработки схемы (без синхронизации: сила, но с авторитетными переходами).

Позже, когда вам нужно изменить схему:

  • Создать миграцию: sequelize migration:create
  • Вставьте файл вверх и вниз в файле миграции
  • В соответствии с вашими изменениями в файле миграции вручную измените свою модель.
  • Запустить 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

Через год все еще полезно, так что поделитесь своими текущими советами. На данный момент я устанавливаю пакет sequelize-cli по мере необходимости live, а затем изменяю сценарии запуска NPM в package.json следующим образом:

...
"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 вручную.

Ответ 2

Просто изучаю это сам, но я думаю, что я бы рекомендовал использовать миграции сейчас, чтобы вы к ним привыкли. Я обнаружил, что для выяснения того, что происходит в процессе миграции, лучше всего взглянуть на sql таблиц, созданных sequelize.sync(), а затем построить миграции оттуда.

migrations -c [migration name] 

Создает файл миграции шаблона в каталоге миграции. Затем вы можете заполнить его полями, которые вам нужны. Этот файл должен содержать 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

Это просто имеет функцию создания, которая выглядит примерно так:

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/ конечно. Но основной ответ заключается в том, что вы должны добавить все в себя, чтобы указать нужные поля. Это не делает это для вас.

Ответ 3

Для разработки теперь есть возможность синхронизировать текущие таблицы, изменяя их структуру. Используя последнюю версию sequelize github repo, вы можете запустить синхронизацию с параметром alter.

Table.sync({alter: true})

Предостережение из документов:

Изменяет таблицы в соответствии с моделями. Не рекомендуется для использования в производстве. Удаляет данные в столбцах, которые были удалены или их тип был изменен в модели.

Ответ 4

Теперь с новой миграцией secelize очень просто.

Это пример того, что вы можете сделать.

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

в конфигурации базы данных.

Ответ 5

Использовать версию. Версия приложения зависит от версии базы данных. Если для новой версии требуется обновление базы данных, создайте для нее миграцию.

update: я решил отказаться от миграции (KISS) и запустить script update_db (sync forse: false), когда он необходимо.

Ответ 6

Немного поздно, и после прочтения документации вам не нужно иметь первую миграцию, о которой вы говорите. Все, что вам нужно сделать, это вызвать sync для создания таблиц.

sequelize.sync()

Вы также можете запустить простую синхронизацию модели, выполнив что-то вроде:

Project.sync(), но я думаю, что sequelize.sync() - более полезный общий случай для вашего проекта (пока вы импортируете хорошие модели во время запуска).

(взято из http://sequelizejs.com/docs/latest/models#database-synchronization)

Это создаст все начальные структуры. После этого вам нужно будет создать миграцию, чтобы развивать свои схемы.

надеюсь, что это поможет.

Ответ 7

Sequelize может запускать произвольный SQL асинхронно.

Что бы я сделал, это:

  • Генерация миграции (для использования в качестве первой миграции);
  • Дамп вашей базы данных, что-то вроде: mysql_dump -uUSER -pPASS DBNAME > FILE.SQL
  • Либо вставьте полный дамп как текст (опасный), либо загрузите файл с полным дампом в Node:
    • var baseSQL = "LOTS OF SQL and it 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 sequelize до тех пор, пока функция асинхронного query будет завершена.

Подробнее о mysql_dump: http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html
Подробнее о Sequelize Migrations: http://sequelize.readthedocs.org/en/latest/docs/migrations/
Подробнее о запуске SQL из Sequelize Migration: https://github.com/sequelize/sequelize/issues/313

Ответ 8

Вот мой текущий рабочий процесс. Я открыт для предложений.

  • Установить sequelize для создания таблиц, которые не существуют
  • Установить сексуализацию для удаления и повторного создания всех таблиц в пустой базе данных, называемой _blank
  • Используйте инструмент mysql для сравнения _blank и изменения синхронизации с использованием этот инструмент. Все еще ищут доступный инструмент, который может макинтош Рабочая среда MySql выглядит так, что вы можете импортировать модель из существующую схему, а затем схему синхронизации. Попытка выяснить, как выполните это через командную строку, чтобы упростить ее.

Таким образом, вам не нужно вручную обновлять таблицу миграции и беспокоиться о толстых пальцах, но вы все равно получаете ORM.

Ответ 9

Друг, у меня был тот же вопрос, и я понял, как им пользоваться.

Я начал без продолжения ORM, поэтому у меня уже была модель данных.
Мне пришлось автоматически генерировать модели с помощью sequelize-auto и генерировать их миграцию с этим файлом, который вы создаете https://gist.github.com/ahelord/a7a7d293695b71aadf04157f0f7dee64 и помещаете синхронизацию ({Force: false})
Это в dev.I пришлось бы моделировать модель и миграции и выполнять их каждый раз, когда я вытаскиваю код.

В процессе производства сервер находится только наверху, поэтому вам нужно только выполнять миграцию и управлять каждой командой, так как вы будете моделировать модель без остановки бэкэнд

Ответ 10

Есть еще более простой способ (избегая Sequalize). Который идет так:

  1. Вы вводите команду внутри вашего проекта: npm run migrate: new

  2. Это создает 3 файла. Файл js и два файла sql с именами вверх и вниз

  3. Вы помещаете свой SQL-оператор в эти файлы, который является чистым SQL
  4. Затем введите: npm run migrate: вверх или npm run migrate: вниз

Чтобы это работало, взгляните на модуль db-migrate.

После того, как вы настроите его (что не сложно), изменение вашей БД действительно легко и экономит много времени.

Ответ 11

Я просмотрел этот пост и другие подобные вопросы, но он мне не ответил. Миграции полезны для ускорения работы локальных баз данных и обновления данных в рабочей среде.

Я задал вопрос здесь и также ответил на него: Рабочий процесс для обработки последовательных миграций и инициализации?

Версия TL-DR для нового проекта

  1. Создайте схему базы данных так, как вы это обычно делаете, используя скрипты на чистом SQL или если вместо этого вы используете графический инструмент
  2. Когда вы доработаете все свои 95% своей схемы БД и будете довольны ею, продолжайте и переместите ее для продолжения, переместив весь файл .sql над
  3. Сделайте свою первую миграцию. Запустите sequelize init:migrate в любой папке, где ваш models находится в
  4. Создайте свой первый файл миграции. Запустите sequelize migration:generate --name [name_of_your_migration]
  5. В этом файле переноса поместите этот код туда
("use strict");
/**
 * DROP SCHEMA public CASCADE; CREATE SCHEMA public
 * ^ there a schema file with all the tables in there. it drops all of that, recreates
 */
const fs = require("fs");
const initialSqlScript = fs.readFileSync("./migrations/sql/Production001.sql", {
  encoding: "utf-8",
});
const db = require("../models");
module.exports = {
  up: () => db.sequelize.query(initialSqlScript),
  down: () =>
    db.sequelize.query('DROP SCHEMA public CASCADE; CREATE SCHEMA public;
'),
};

enter image description here

с этой общей структурой папок

enter image description here

  1. Теперь ваши настройки секвелирования синхронизируются с вашей исходной схемой базы данных
  2. когда вы хотите отредактировать схему базы данных, запустите это снова sequelize migration:generate --name [name_of_your_migration]
  3. Продолжайте вносить изменения в пути миграции up и down. Это ваши операторы ALTER для изменения имен столбцов, DELETE, ADD столбцов и т.д.
  4. Запустите sequelize db:migrate
  5. Вы хотите, чтобы модели были синхронизированы с изменениями в вашей удаленной базе данных, поэтому теперь вы можете сделать npm install sequelize-auto.
  6. Это будет считывать текущую схему базы данных в вашей базе данных и автоматически генерировать файлы модели. Используйте команду, подобную этой sequelize-auto -o "./models" -d sequelize_auto_test -h localhost -u my_username -p 5432 -x my_password -e postgres, найденную в https://github.com/sequelize/sequelize-auto

Вы можете использовать git, чтобы увидеть difflogs в вашей модели, должны быть только изменения, отражающие изменения в модели базы данных. В качестве примечания, никогда не изменяйте models напрямую, если вы используете sequelize auto, так как это сгенерирует их для вас. Точно так же вам больше не нужно изменять схему базы данных напрямую с помощью файлов SQL, если это опция, поскольку вы также можете импортировать эти файлы .sql

Теперь ваша схема базы данных обновлена, и вы официально перешли к сиквелизации только миграции баз данных.

Все контролируется версией. Это идеальный рабочий процесс для базы данных и внутреннего разработчика