Миграции баз данных — это изменения, вносимые в базу данных. Эти изменения могут включать в себя изменение схемы таблицы, обновление данных в наборе записей, заполнение данных или удаление диапазона записей.
Миграции баз данных, как правило, выполняются перед запуском приложения и не выполняются успешно более одного раза для одной и той же базы данных. Инструменты миграции баз данных сохраняют историю миграций, которые были выполнены в базе данных, чтобы их можно было отслеживать для будущих целей.
В этой статье вы узнаете, как настроить и выполнить миграции баз данных в минимальном приложении API на Node.js. Мы будем использовать ts-migrate-mongoose и скрипт npm для создания миграции и заполнения данных в базе данных MongoDB. ts-migrate-mongoose поддерживает выполнение миграционных скриптов из кода TypeScript, а также кода CommonJS.
ts-migrate-mongoose — это фреймворк миграций для проектов на Node.js, которые используют mongoose в качестве сопоставителя объект-данные. Он предоставляет шаблон для написания миграционных скриптов. Также он предоставляет конфигурацию для программного запуска скриптов и из командной строки.
Содержание
-
Как засеять пользовательские данные с помощью ts-migrate-mongoose
-
Как создать конечную точку API для получения засеянных данных
Как настроить проект
Для использования ts-migrate-mongoose для миграций базы данных вам понадобится следующее:
-
Проект Node.js с установленным mongoose в качестве зависимости.
-
База данных MongoDB, подключенная к проекту.
-
MongoDB Compass (необязательно – для того, чтобы мы могли видеть изменения в базе данных).
Создан репозиторий-стартер, который можно клонировать из ts-migrate-mongoose-starter-repo для удобства. Клонируйте репозиторий, заполните переменные окружения и запустите приложение, выполнив команду npm start
.
Посетите http://localhost:8000 с помощью браузера или клиента API, такого как Postman, и сервер вернет текст “Hello there!”, чтобы показать, что стартовое приложение работает как ожидалось.
Как настроить ts-migrate-mongoose для проекта
Чтобы настроить ts-migrate-mongoose для проекта, установите ts-migrate-mongoose с помощью этой команды:
npm install ts-migrate-mongoose
ts-migrate-mongoose позволяет настраивать с помощью JSON файла, TypeScript файла, файла .env
или через CLI. Рекомендуется использовать файл .env
, так как содержимое конфигурации может содержать пароль от базы данных, и неуместно, чтобы это было доступно публично. Файлы .env
обычно скрыты через файлы .gitignore
, что делает их более безопасными для использования. Этот проект будет использовать файл .env
для конфигурации ts-migrate-mongoose.
Файл должен содержать следующие ключи и их значения:
-
MIGRATE_MONGO_URI
– URI базы данных Mongo. Это то же самое, что и URL базы данных. -
MIGRATE_MONGO_COLLECTION
– имя коллекции (или таблицы), в которой должны быть сохранены миграции. Значение по умолчанию – migrations, что используется в этом проекте. ts-migrate-mongoose сохраняет миграции в MongoDB. -
MIGRATE_MIGRATIONS_PATH
– путь к папке для хранения и чтения скриптов миграции. Значение по умолчанию –./migrations
, что используется в этом проекте.
Как заполнить данные пользователей с помощью ts-migrate-mongoose
Мы смогли создать проект и успешно подключить его к базе данных Mongo. На этом этапе мы хотим заполнить данные пользователей в базу данных. Нам нужно:
-
Создать коллекцию пользователей
-
Использовать ts-migrate-mongoose для создания скрипта миграции для заполнения данных
-
Использовать ts-migrate-mongoose для запуска миграции для заполнения данных пользователей в базу данных перед запуском приложения
1. Создайте коллекцию пользователей с помощью Mongoose
Схема Mongoose может быть использована для создания коллекции пользователей (или таблицы). Документы пользователей (или записи) будут иметь следующие поля (или столбцы): email
, favouriteEmoji
и yearOfBirth
.
Чтобы создать схему Mongoose для коллекции пользователей, создайте файл user.model.js
в корне проекта, содержащий следующий фрагмент кода:
const mongoose = require("mongoose");
const userSchema = new mongoose.Schema(
{
email: {
type: String,
lowercase: true,
required: true,
},
favouriteEmoji: {
type: String,
required: true,
},
yearOfBirth: {
type: Number,
required: true,
},
},
{
timestamps: true,
}
);
module.exports.UserModel = mongoose.model("User", userSchema);
2. Создайте скрипт миграции с помощью ts-migrate-mongoose
ts-migrate-mongoose предоставляет интерфейс командной строки (CLI), который можно использовать для создания скриптов миграции.
Запуск npx migrate create <имя-скрипта>
в корневой папке проекта создаст скрипт в папке MIGRATE_MIGRATIONS_PATH
(в нашем случае ./migrations
). <имя-скрипта>
– это имя, которое мы хотим, чтобы у файла скрипта миграции после его создания.
Для создания скрипта миграции для заполнения данных пользователей, выполните:
npx migrate create seed-users
Команда создаст файл в папке ./migrations
с именем в формате – <timestamp>-seed-users.ts
. Файл будет содержать следующее содержимое фрагмента кода:
// Импортируйте ваши модели здесь
export async function up (): Promise<void> {
// Напишите миграцию здесь
}
export async function down (): Promise<void> {
// Напишите миграцию здесь
}
Функция up
используется для запуска миграции. Функция down
используется для отмены действий, выполненных функцией up
, если это необходимо. В нашем случае мы пытаемся добавить пользователей в базу данных. Функция up
будет содержать код для добавления пользователей в базу данных, а функция down
будет содержать код для удаления пользователей, созданных функцией up
.
Если база данных проверяется с помощью MongoDB Compass, в коллекции миграций будет документ, который выглядит следующим образом:
{
"_id": ObjectId("6744740465519c3bd9c1a7d1"),
"name": "seed-users",
"state": "down",
"createdAt": 2024-11-25T12:56:36.316+00:00,
"updatedAt": 2024-11-25T12:56:36.316+00:00,
"__v": 0
}
Поле state
документа миграции установлено в down
. После успешного выполнения оно изменится на up
.
Вы можете обновить код в ./migrations/<timestamp>-seed-users.ts
на приведенный ниже:
require("dotenv").config() // загрузить переменные среды
const db = require("../db.js")
const { UserModel } = require("../user.model.js");
const seedUsers = [
{ email: "[email protected]", favouriteEmoji: "🏃", yearOfBirth: 1997 },
{ email: "[email protected]", favouriteEmoji: "🍏", yearOfBirth: 1998 },
];
export async function up (): Promise<void> {
await db.connect(process.env.MONGO_URI)
await UserModel.create(seedUsers);}
export async function down (): Promise<void> {
await db.connect(process.env.MONGO_URI)
await UserModel.delete({
email: {
$in: seedUsers.map((u) => u.email),
},
});
}
3. Запуск миграции перед запуском приложения
ts-migrate-mongoose предоставляет нам команды CLI для выполнения функций up
и down
скриптов миграции.
С помощью npx migrate up <name-of-script>
мы можем выполнить функцию up
определенного скрипта. С помощью npx migrate up
мы можем выполнить функцию up
всех скриптов в папке ./migrations
со значением state
равным down
в базе данных.
Для запуска миграции перед запуском приложения мы используем npm-скрипты. npm-скрипты с префиксом pre
будут выполняться перед скриптом без префикса pre
. Например, если есть скрипт dev
и скрипт predev
, то при запуске скрипта dev
с помощью npm run dev
, скрипт predev
будет автоматически запускаться перед выполнением скрипта dev
.
Мы будем использовать эту функцию npm-скриптов, чтобы поместить команду ts-migrate-mongoose в скрипт prestart
, чтобы миграция выполнялась перед запуском скрипта start
.
Обновите файл package.json
, чтобы добавить скрипт prestart
, который будет запускать команду ts-migrate-mongoose для выполнения функции up
миграционных скриптов в проекте.
"scripts": {
"prestart": "npx migrate up",
"start": "node index.js"
},
С этой настройкой, при выполнении команды npm run start
для запуска приложения будет выполняться скрипт prestart
для выполнения миграции с использованием ts-migrate-mongoose и заполнения базы данных перед запуском приложения.
После выполнения команды npm run start
у вас должно быть что-то похожее на следующий отрывок:
Synchronizing database with file system migrations...
MongoDB connection successful
up: 1732543529744-seed-users.ts
All migrations finished successfully
> [email protected] start
> node index.js
MongoDB connection successful
Server listening on port 8000
Ознакомьтесь с веткой seed-users репозитория, чтобы увидеть текущее состояние кодовой базы на данном этапе в статье.
Как создать конечную точку API для получения данных о пользователе
Мы можем создать конечную точку API для получения данных о засеянных пользователях в нашей базе данных. В файле server.js
обновите код на тот, что приведен в отрывке ниже:
const { UserModel } = require("./user.model.js")
module.exports = async function (req, res) {
const users = await UserModel.find({}) // получить всех пользователей в базе данных
res.writeHead(200, { "Content-Type": "application/json" });
return res.end(JSON.stringify({ // вернуть JSON-представление данных о полученных пользователях
users: users.map((u) => ({
email: u.email,
favouriteEmoji: u.favouriteEmoji,
yearOfBirth: u.yearOfBirth,
createdAt: u.createdAt
}))
}, null, 2));
};
Если мы запустим приложение и посетим http://localhost:8000 с помощью Postman или браузера, мы получим JSON-ответ, подобный приведенному ниже:
{
"users": [
{
"email": "[email protected]",
"favouriteEmoji": "🏃",
"yearOfBirth": 1997,
"createdAt": "2024-11-25T14:18:55.416Z"
},
{
"email": "[email protected]",
"favouriteEmoji": "🍏",
"yearOfBirth": 1998,
"createdAt": "2024-11-25T14:18:55.416Z"
}
]
}
Обратите внимание, что если приложение будет запущено снова, скрипт миграции больше не будет запущен, потому что state
миграции теперь будет up
, после успешного выполнения.
Проверьте ветку fetch-users в репозитории, чтобы увидеть текущий статус кодовой базы на этом этапе в статье.
Заключение
Миграции полезны при создании приложений и есть необходимость в заполнении начальных данных для тестирования, заполнении административных пользователей, обновлении схемы базы данных путем добавления или удаления колонок и обновлении значений колонок во многих записях одновременно.
ts-migrate-mongoose может помочь создать фреймворк для выполнения миграций для ваших приложений Node.js, если вы используете Mongoose с MongoDB.
Source:
https://www.freecodecamp.org/news/handle-mongodb-migrations-with-ts-migrate-mongoose/