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). Который идет так:
-
Вы вводите команду внутри вашего проекта: npm run migrate: new
-
Это создает 3 файла. Файл js и два файла sql с именами вверх и вниз
- Вы помещаете свой SQL-оператор в эти файлы, который является чистым SQL
- Затем введите: npm run migrate: вверх или npm run migrate: вниз
Чтобы это работало, взгляните на модуль db-migrate.
После того, как вы настроите его (что не сложно), изменение вашей БД действительно легко и экономит много времени.
Ответ 11
Я просмотрел этот пост и другие подобные вопросы, но он мне не ответил. Миграции полезны для ускорения работы локальных баз данных и обновления данных в рабочей среде.
Я задал вопрос здесь и также ответил на него: Рабочий процесс для обработки последовательных миграций и инициализации?
Версия TL-DR для нового проекта
- Создайте схему базы данных так, как вы это обычно делаете, используя скрипты на чистом SQL или если вместо этого вы используете графический инструмент
- Когда вы доработаете все свои 95% своей схемы БД и будете довольны ею, продолжайте и переместите ее для продолжения, переместив весь файл
.sql
над
- Сделайте свою первую миграцию. Запустите
sequelize init:migrate
в любой папке, где ваш models
находится в
- Создайте свой первый файл миграции. Запустите
sequelize migration:generate --name [name_of_your_migration]
- В этом файле переноса поместите этот код туда
("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]()
- Теперь ваши настройки секвелирования синхронизируются с вашей исходной схемой базы данных
- когда вы хотите отредактировать схему базы данных, запустите это снова
sequelize migration:generate --name [name_of_your_migration]
- Продолжайте вносить изменения в пути миграции
up
и down
. Это ваши операторы ALTER для изменения имен столбцов, DELETE, ADD столбцов и т.д.
- Запустите
sequelize db:migrate
- Вы хотите, чтобы модели были синхронизированы с изменениями в вашей удаленной базе данных, поэтому теперь вы можете сделать
npm install sequelize-auto
.
- Это будет считывать текущую схему базы данных в вашей базе данных и автоматически генерировать файлы модели. Используйте команду, подобную этой
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
Теперь ваша схема базы данных обновлена, и вы официально перешли к сиквелизации только миграции баз данных.
Все контролируется версией. Это идеальный рабочий процесс для базы данных и внутреннего разработчика