Миграции
Так же, как вы используете Git / SVN для управления изменениями в исходном коде, вы можете использовать миграции для отслеживания изменений в базе данных. С помощью миграций вы можете перенести вашу существующую базу данных в другое состояние и наоборот: эти переходы состояния сохраняются в файлах миграций, которые описывают, как перейти к новому состоянию и как откатить изменения, чтобы вернуться к старому состоянию.
Вам понадобится Sequelize CLI. CLI предоставляет поддержку миграций и создания проекта.
CLI
Установка CLI
Начнем с установки CLI, инструкции вы можете найти здесь. Самый предпочтительный способ — установка локально, как показано ниже
$ npm install --save sequelize-cli
Создание проекта
Для создания пустого проекта вам нужно выполнить команду init
$ npx sequelize-cli init
Это создаст следующие папки
-
config, содержит файл конфигурации, который сообщает CLI, как подключиться к базе данных -
models, содержит все модели для вашего проекта -
migrations, содержит все файлы миграций -
seeders, содержит все файлы семян
Конфигурация
Прежде чем продолжить, нам нужно указать CLI, как подключиться к базе данных. Для этого откроем файл конфигурации по умолчанию config/config.json. Он выглядит примерно так
{
"development": {
"username": "root",
"password": null,
"database": "database_development",
"host": "127.0.0.1",
"dialect": "mysql"
},
"test": {
"username": "root",
"password": null,
"database": "database_test",
"host": "127.0.0.1",
"dialect": "mysql"
},
"production": {
"username": "root",
"password": null,
"database": "database_production",
"host": "127.0.0.1",
"dialect": "mysql"
}
}
Теперь отредактируйте этот файл и укажите правильные учетные данные базы данных и диалект. Ключи объектов (например, "development") используются в model/index.js для сопоставления process.env.NODE_ENV (Если не определено, "development" — значение по умолчанию.).
Примечание: Если ваша база данных еще не существует, вы можете просто вызвать команду db:create. При правильном доступе она создаст базу данных для вас.
Создание первой модели (и миграции)
После правильной конфигурации файла конфигурации CLI вы готовы создать свою первую миграцию. Это так же просто, как выполнение простой команды.
Мы будем использовать команду model:generate. Эта команда требует двух параметров
-
name, имя модели -
attributes, список атрибутов модели
Давайте создадим модель с именем User.
$ npx sequelize-cli model:generate --name User --attributes firstName:string,lastName:string,email:string
Это сделает следующее
- Создаст файл модели
userв папкеmodels - Создаст файл миграции с именем, похожим на
XXXXXXXXXXXXXX-create-user.jsв папкеmigrations
Примечание: Sequelize будет использовать только файлы моделей, это представление таблицы. С другой стороны, файл миграции — это изменение в этой модели или, точнее, в этой таблице, используемый CLI. Считайте миграции как коммит или журнал для каких-либо изменений в базе данных.
Выполнение миграций
До этого шага мы ничего не вставляли в базу данных. Мы только что создали необходимые файлы модели и миграции для нашей первой модели User. Теперь, чтобы фактически создать эту таблицу в базе данных, вам нужно выполнить команду db:migrate.
$ npx sequelize-cli db:migrate
Эта команда выполнит следующие действия:
- Обеспечит наличие таблицы под названием
SequelizeMetaв базе данных. Эта таблица используется для записи того, какие миграции были выполнены в текущей базе данных - Начнет поиск любых файлов миграций, которые еще не были выполнены. Это возможно, проверив таблицу
SequelizeMeta. В этом случае она выполнит миграциюXXXXXXXXXXXXXX-create-user.js, которую мы создали на последнем шаге. - Создаст таблицу под названием
Usersсо всеми столбцами, как указано в ее файле миграции.
Отмена миграций
Теперь наша таблица была создана и сохранена в базе данных. С помощью миграций вы можете вернуться к старому состоянию, просто выполнив команду.
Вы можете использовать db:migrate:undo, эта команда отменит последнюю миграцию.
$ npx sequelize-cli db:migrate:undo
Вы можете вернуться к исходному состоянию, отменив все миграции с помощью команды db:migrate:undo:all . Вы также можете вернуться к определенной миграции, передав ее имя в опции --to.
$ npx sequelize-cli db:migrate:undo:all --to XXXXXXXXXXXXXX-create-posts.js
Создание первого семян
Предположим, мы хотим вставить некоторые данные в несколько таблиц по умолчанию. Если мы продолжим предыдущий пример, мы можем рассмотреть создание демонстрационного пользователя для таблицы User.
Для управления всеми миграциями данных вы можете использовать сеедеры. Файлы семян — это некоторые изменения в данных, которые могут использоваться для заполнения таблицы базы данных образцовыми данными или тестовыми данными.
Давайте создадим файл семян, который добавит демонстрационного пользователя в нашу таблицу User.
$ npx sequelize-cli seed:generate --name demo-user
Эта команда создаст файл семян в папке seeders . Имя файла будет выглядеть примерно как XXXXXXXXXXXXXX-demo-user.js. Он следует той же семантике up / down, что и файлы миграций.
Теперь мы должны отредактировать этот файл, чтобы вставить демонстрационного пользователя в таблицу User.
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.bulkInsert('Users', [{
firstName: 'John',
lastName: 'Doe',
email: 'demo@demo.com',
createdAt: new Date(),
updatedAt: new Date()
}], {});
},
down: (queryInterface, Sequelize) => {
return queryInterface.bulkDelete('Users', null, {});
}
};
Выполнение семян
На последнем шаге вы создали файл семян. Он все еще не сохранен в базе данных. Для этого нам нужно выполнить простую команду.
$ npx sequelize-cli db:seed:all
Это выполнит этот файл семян, и у вас будет демонстрационный пользователь, вставленный в таблицу User.
Примечание: Выполнение семян не хранится нигде, в отличие от миграций, которые используют таблицу SequelizeMeta. Если вы хотите переопределить это, пожалуйста, прочитайте раздел Storage
Отмена семян
Семена можно отменить, если они используют какое-либо хранилище. Для этого доступны две команды:
Если вы хотите отменить последнее семя
$ npx sequelize-cli db:seed:undo
Если вы хотите отменить конкретное семя
$ npx sequelize-cli db:seed:undo --seed name-of-seed-as-in-data
Если вы хотите отменить все семена
$ npx sequelize-cli db:seed:undo:all
Дополнительные темы
Шаблон миграции
Следующий шаблон показывает типичный файл миграции.
module.exports = {
up: (queryInterface, Sequelize) => {
// logic for transforming into the new state
},
down: (queryInterface, Sequelize) => {
// logic for reverting the changes
}
}
Мы можем сгенерировать этот файл, используя migration:generate. Это создаст xxx-migration-skeleton.js в вашей папке миграций.
$ npx sequelize-cli migration:generate --name migration-skeleton
Переданный объект queryInterface может использоваться для изменения базы данных. Объект Sequelize хранит доступные типы данных, такие как STRING или INTEGER. Функции up или down должны возвращать Promise. Давайте посмотрим на пример:
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Person', {
name: Sequelize.STRING,
isBetaMember: {
type: Sequelize.BOOLEAN,
defaultValue: false,
allowNull: false
}
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Person');
}
}
Следующий пример миграции выполняет два изменения в базе данных, используя транзакцию, чтобы убедиться, что все инструкции успешно выполнены или отменены в случае сбоя:
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.sequelize.transaction((t) => {
return Promise.all([
queryInterface.addColumn('Person', 'petName', {
type: Sequelize.STRING
}, { transaction: t }),
queryInterface.addColumn('Person', 'favoriteColor', {
type: Sequelize.STRING,
}, { transaction: t })
])
})
},
down: (queryInterface, Sequelize) => {
return queryInterface.sequelize.transaction((t) => {
return Promise.all([
queryInterface.removeColumn('Person', 'petName', { transaction: t }),
queryInterface.removeColumn('Person', 'favoriteColor', { transaction: t })
])
})
}
};
Следующий пример миграции имеет внешний ключ. Вы можете использовать ссылки для указания внешнего ключа:
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Person', {
name: Sequelize.STRING,
isBetaMember: {
type: Sequelize.BOOLEAN,
defaultValue: false,
allowNull: false
},
userId: {
type: Sequelize.INTEGER,
references: {
model: {
tableName: 'users',
schema: 'schema'
}
key: 'id'
},
allowNull: false
},
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Person');
}
}
Следующий пример миграции использует async/await, где вы создаете уникальный индекс в новом столбце:
module.exports = {
async up(queryInterface, Sequelize) {
const transaction = await queryInterface.sequelize.transaction();
try {
await queryInterface.addColumn(
'Person',
'petName',
{
type: Sequelize.STRING,
},
{ transaction }
);
await queryInterface.addIndex(
'Person',
'petName',
{
fields: 'petName',
unique: true,
},
{ transaction }
);
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
},
async down(queryInterface, Sequelize) {
const transaction = await queryInterface.sequelize.transaction();
try {
await queryInterface.removeColumn('Person', 'petName', { transaction });
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
},
};
Файл .sequelizerc
Это специальный файл конфигурации. Он позволяет указать следующие параметры, которые обычно передаются в качестве аргументов в CLI:
-
env: Среда выполнения команды -
config: Путь к файлу конфигурации -
options-path: Путь к JSON-файлу с дополнительными параметрами -
migrations-path: Путь к папке миграций -
seeders-path: Путь к папке семян -
models-path: Путь к папке моделей -
url: Строка подключения к базе данных для использования. Альтернатива использованию файлов конфигурации -
debug: При наличии отображает различную отладочную информацию
Некоторые сценарии, где вы можете его использовать.
- Вы хотите переопределить путь по умолчанию к папке
migrations,models,seedersилиconfig. - Вы хотите переименовать папку
config.jsonв что-то другое, например,database.json
И многое другое. Давайте посмотрим, как вы можете использовать этот файл для пользовательской конфигурации.
Для начала создадим пустой файл в корневой директории вашего проекта.
$ touch .sequelizerc
Теперь давайте поработаем с примером конфигурации.
const path = require('path');
module.exports = {
'config': path.resolve('config', 'database.json'),
'models-path': path.resolve('db', 'models'),
'seeders-path': path.resolve('db', 'seeders'),
'migrations-path': path.resolve('db', 'migrations')
}
С этой конфигурацией вы сообщаете CLI:
- Использовать файл
config/database.jsonдля параметров конфигурации - Использовать
db/modelsв качестве папки моделей - Использовать
db/seedersв качестве папки семян - Использовать
db/migrationsв качестве папки миграций
Динамическая конфигурация
Файл конфигурации по умолчанию — это JSON-файл с именем config.json. Но иногда вы хотите выполнить некоторый код или получить доступ к переменным среды, что невозможно в JSON-файлах.
Sequelize CLI может читать как из файлов JSON, так и из файлов JS. Это можно настроить с помощью файла .sequelizerc . Посмотрим как
Сначала вам нужно создать файл .sequelizerc в корневой папке вашего проекта. Этот файл должен переопределить путь к конфигурации на файл JS. Так:
const path = require('path');
module.exports = {
'config': path.resolve('config', 'config.js')
}
Теперь Sequelize CLI загрузит config/config.js для получения параметров конфигурации. Поскольку это JS-файл, вы можете выполнить любой код и экспортировать конечный динамический файл конфигурации.
Пример файла config/config.js
const fs = require('fs');
module.exports = {
development: {
username: 'database_dev',
password: 'database_dev',
database: 'database_dev',
host: '127.0.0.1',
dialect: 'mysql'
},
test: {
username: 'database_test',
password: null,
database: 'database_test',
host: '127.0.0.1',
dialect: 'mysql'
},
production: {
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
host: process.env.DB_HOSTNAME,
dialect: 'mysql',
dialectOptions: {
ssl: {
ca: fs.readFileSync(__dirname + '/mysql-ca-master.crt')
}
}
}
};
Использование Babel
Теперь вы знаете, как использовать файл .sequelizerc . Теперь давайте посмотрим, как использовать этот файл для настройки Babel с sequelize-cli. Это позволит вам писать миграции и семена с синтаксисом ES6/ES7.
Сначала установите babel-register
$ npm i --save-dev babel-register
Теперь давайте создадим файл .sequelizerc , он может содержать любую конфигурацию, которую вы хотите изменить для sequelize-cli, но помимо этого мы хотим зарегистрировать Babel для нашего кода. Что-то вроде этого
$ touch .sequelizerc # Create rc file
Теперь включите настройку babel-register в этот файл
require("babel-register");
const path = require('path');
module.exports = {
'config': path.resolve('config', 'config.json'),
'models-path': path.resolve('models'),
'seeders-path': path.resolve('seeders'),
'migrations-path': path.resolve('migrations')
}
Теперь CLI сможет запускать код ES6/ES7 из миграций/семян и т. д. Пожалуйста, имейте в виду, что это зависит от вашей конфигурации .babelrc. Подробнее об этом можно узнать на babeljs.io.
Использование переменных среды
С помощью CLI вы можете напрямую получить доступ к переменным среды внутри config/config.js. Вы можете использовать .sequelizerc для указания CLI использовать config/config.js для конфигурации. Это объясняется в последнем разделе.
Затем вы можете просто экспонировать файл с соответствующими переменными среды.
module.exports = {
development: {
username: 'database_dev',
password: 'database_dev',
database: 'database_dev',
host: '127.0.0.1',
dialect: 'mysql'
},
test: {
username: process.env.CI_DB_USERNAME,
password: process.env.CI_DB_PASSWORD,
database: process.env.CI_DB_NAME,
host: '127.0.0.1',
dialect: 'mysql'
},
production: {
username: process.env.PROD_DB_USERNAME,
password: process.env.PROD_DB_PASSWORD,
database: process.env.PROD_DB_NAME,
host: process.env.PROD_DB_HOSTNAME,
dialect: 'mysql'
}
};
Указание параметров диалекта
Иногда вы хотите указать параметр диалекта, если это общая конфигурация, вы можете добавить ее в config/config.json. Иногда вы хотите выполнить некоторый код для получения параметров диалекта, в этих случаях вы должны использовать файл динамической конфигурации.
{
"production": {
"dialect":"mysql",
"dialectOptions": {
"bigNumberStrings": true
}
}
}
Использование в производственной среде
Несколько советов по использованию CLI и настройки миграций в производственной среде.
1) Используйте переменные среды для параметров конфигурации. Это лучше всего достигается с помощью динамической конфигурации. Пример безопасной для производства конфигурации может выглядеть так.
const fs = require('fs');
module.exports = {
development: {
username: 'database_dev',
password: 'database_dev',
database: 'database_dev',
host: '127.0.0.1',
dialect: 'mysql'
},
test: {
username: 'database_test',
password: null,
database: 'database_test',
host: '127.0.0.1',
dialect: 'mysql'
},
production: {
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
host: process.env.DB_HOSTNAME,
dialect: 'mysql',
dialectOptions: {
ssl: {
ca: fs.readFileSync(__dirname + '/mysql-ca-master.crt')
}
}
}
};
Наша цель — использовать переменные среды для различных секретов базы данных и не случайно проверять их в систему управления версиями.
Хранилище
Есть три типа хранилищ, которые вы можете использовать: sequelize, json, и none.
-
sequelize: хранит миграции и семена в таблице базы данных sequelize -
json: хранит миграции и семена в файле json -
none: не хранит никакие миграции/семена
Хранение миграций
По умолчанию CLI создаст таблицу в вашей базе данных под названием SequelizeMeta содержащую запись для каждой выполненной миграции. Для изменения этого поведения, есть три варианта, которые вы можете добавить в конфигурационный файл. Используя migrationStorage, вы можете выбрать тип хранения, который будет использоваться для миграций. Если вы выберите json, вы можете указать путь к файлу, используя migrationStoragePath, или CLI запишет в файл sequelize-meta.json. Если вы хотите сохранить информацию в базе данных, используя sequelize, но хотите использовать другую таблицу, вы можете изменить имя таблицы, используя migrationStorageTableName. Также вы можете определить другую схему для таблицы SequelizeMeta , указав свойство migrationStorageTableSchema.
{
"development": {
"username": "root",
"password": null,
"database": "database_development",
"host": "127.0.0.1",
"dialect": "mysql",
// Use a different storage type. Default: sequelize
"migrationStorage": "json",
// Use a different file name. Default: sequelize-meta.json
"migrationStoragePath": "sequelizeMeta.json",
// Use a different table name. Default: SequelizeMeta
"migrationStorageTableName": "sequelize_meta",
// Use a different schema for the SequelizeMeta table
"migrationStorageTableSchema": "custom_schema"
}
}
Примечание: Хранение none не рекомендуется в качестве хранения миграций. Если вы решите его использовать, будьте осведомлены о последствиях отсутствия записи о выполненных или не выполненных миграциях.
Хранение семян
По умолчанию CLI не будет сохранять никакие выполненные семена. Если вы хотите изменить это поведение, вы можете использовать seederStorage в конфигурационном файле, чтобы изменить тип хранения. Если вы выберите json, вы можете указать путь к файлу, используя seederStoragePath, или CLI запишет в файл sequelize-data.json. Если вы хотите сохранить информацию в базе данных, используя sequelize, вы можете указать имя таблицы, используя seederStorageTableName, или оно будет установлено по умолчанию как SequelizeData.
{
"development": {
"username": "root",
"password": null,
"database": "database_development",
"host": "127.0.0.1",
"dialect": "mysql",
// Use a different storage. Default: none
"seederStorage": "json",
// Use a different file name. Default: sequelize-data.json
"seederStoragePath": "sequelizeData.json",
// Use a different table name. Default: SequelizeData
"seederStorageTableName": "sequelize_data"
}
}
Строка подключения конфигурации
В качестве альтернативы варианту --config с конфигурационными файлами, определяющими вашу базу данных, вы можете использовать вариант --url для передачи строки подключения. Например:
$ npx sequelize-cli db:migrate --url 'mysql://root:password@mysql_host.com/database_name'
Передача диалектно-специфичных опций
{
"production": {
"dialect":"postgres",
"dialectOptions": {
// dialect options like SSL etc here
}
}
}
Программное использование
У Sequelize есть сестринская библиотека для программного управления выполнением и ведением журнала задач миграции.
Интерфейс запроса
Используя объект queryInterface , описанный ранее, вы можете изменить схему базы данных. Чтобы увидеть полный список поддерживаемых публичных методов, проверьте API интерфейса запросов
Copyright © 2014–present Sequelize contributors
Licensed under the MIT License.
https://sequelize.org/v5/manual/migrations.html