Las migraciones de bases de datos son modificaciones realizadas en una base de datos. Estas modificaciones pueden incluir cambios en el esquema de una tabla, actualización de datos en un conjunto de registros, inserción de datos o eliminación de un rango de registros.
Las migraciones de bases de datos generalmente se ejecutan antes de que una aplicación comience y no se ejecutan con éxito más de una vez para la misma base de datos. Las herramientas de migración de bases de datos guardan un historial de migraciones que se han ejecutado en una base de datos para que puedan ser rastreadas para futuros propósitos.
En este artículo, aprenderás cómo configurar y ejecutar migraciones de bases de datos en una aplicación mínima de API en Node.js. Usaremos ts-migrate-mongoose y un script de npm para crear una migración e insertar datos en una base de datos MongoDB. ts-migrate-mongoose admite la ejecución de scripts de migración desde código TypeScript, así como desde código CommonJS.
ts-migrate-mongoose es un marco de migración para proyectos de Node.js que utilizan mongoose como el mapeador objeto-dato. Proporciona una plantilla para escribir scripts de migración. También proporciona una configuración para ejecutar los scripts de manera programática y desde la CLI.
Tabla de Contenidos
Cómo configurar el proyecto
Para usar ts-migrate-mongoose para migraciones de base de datos, necesitas tener lo siguiente:
-
Un proyecto Node.js con mongoose instalado como dependencia.
-
Una base de datos MongoDB conectada al proyecto.
-
MongoDB Compass (Opcional – para permitirnos ver los cambios en la base de datos).
Se ha creado un repositorio inicial que se puede clonar desde ts-migrate-mongoose-starter-repo para mayor facilidad. Clone el repositorio, complete las variables de entorno y inicie la aplicación ejecutando el comando npm start
.
Visite http://localhost:8000 con un navegador o un cliente de API como Postman y el servidor devolverá un texto “¡Hola!” para demostrar que la aplicación inicial se está ejecutando como se espera.
Cómo configurar ts-migrate-mongoose para el proyecto
Para configurar ts-migrate-mongoose para el proyecto, instale ts-migrate-mongoose con este comando:
npm install ts-migrate-mongoose
ts-migrate-mongoose permite la configuración con un archivo JSON, un archivo TypeScript, un archivo .env
o a través de la CLI. Se recomienda usar un archivo .env
porque el contenido de la configuración puede contener una contraseña de base de datos y no es adecuado exponerla al público. Los archivos .env
suelen estar ocultos a través de archivos .gitignore
por lo que son más seguros de usar. Este proyecto usará un archivo .env
para la configuración de ts-migrate-mongoose.
El archivo debería contener las siguientes claves y sus valores:
-
MIGRATE_MONGO_URI
– la URI de la base de datos Mongo. Es igual que la URL de la base de datos. -
MIGRATE_MONGO_COLLECTION
– el nombre de la colección (o tabla) en la que se deben guardar las migraciones. El valor predeterminado es “migrations”, que es lo que se usa en este proyecto. ts-migrate-mongoose guarda las migraciones en MongoDB. -
MIGRATE_MIGRATIONS_PATH
– la ruta a la carpeta para almacenar y leer los scripts de migración. El valor predeterminado es./migrations
, que es lo que se usa en este proyecto.
Cómo sembrar datos de usuario con ts-migrate-mongoose
Hemos logrado crear un proyecto y conectarlo con éxito a una base de datos de Mongo. En este punto, queremos sembrar datos de usuario en la base de datos. Necesitamos:
-
Crear una colección (o tabla) de usuarios
-
Usar ts-migrate-mongoose para crear un script de migración para sembrar datos
-
Usar ts-migrate-mongoose para ejecutar la migración y sembrar los datos de usuario en la base de datos antes de que la aplicación empiece
1. Cree una colección de usuarios usando Mongoose
El esquema de Mongoose se puede utilizar para crear una colección de usuarios (o tabla). Los documentos de usuario (o registros) tendrán los siguientes campos (o columnas): email
, favouriteEmoji
y yearOfBirth
.
Para crear un esquema de Mongoose para la colección de usuarios, cree un archivo user.model.js
en la raíz del proyecto que contenga el siguiente fragmento de código:
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. Cree un Script de Migración con ts-migrate-mongoose
ts-migrate-mongoose proporciona comandos de CLI que se pueden utilizar para crear scripts de migración.
Al ejecutar npx migrate create <nombre-del-script>
en la carpeta raíz del proyecto se creará un script en la carpeta MIGRATE_MIGRATIONS_PATH
(./migrations
en nuestro caso). <nombre-del-script>
es el nombre que queremos que tenga el archivo de script de migración cuando se crea.
Para crear un script de migración para cargar datos de usuario, ejecute:
npx migrate create seed-users
El comando creará un archivo en la carpeta ./migrations
con un nombre en la forma –<marca-de-tiempo>-seed-users.ts
. El archivo tendrá el siguiente contenido del fragmento de código:
// Importa tus modelos aquí
export async function up (): Promise<void> {
// Escribe la migración aquí
}
export async function down (): Promise<void> {
// Escribe la migración aquí
}
La función up
se utiliza para ejecutar la migración. La función down
se utiliza para revertir lo que sea que la función up
ejecute, si es necesario. En nuestro caso, estamos intentando insertar usuarios en la base de datos. La función up
contendrá código para insertar usuarios en la base de datos y la función down
contendrá código para eliminar usuarios creados en la función up
.
Si la base de datos se inspecciona con MongoDB Compass, la colección de migraciones tendrá un documento que se verá así:
{
"_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
}
El campo state
del documento de migración está establecido en down
. Después de que se ejecute con éxito, cambia a up
.
Puedes actualizar el código en ./migrations/<timestamp>-seed-users.ts
al que se muestra en el fragmento a continuación:
require("dotenv").config() // cargar variables de entorno
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. Ejecutar la Migración Antes de que Inicie la Aplicación
ts-migrate-mongoose nos proporciona comandos de CLI para ejecutar la función up
y down
de los scripts de migración.
Con npx migrate up <nombre-del-script>
podemos ejecutar la función up
de un script específico. Con npx migrate up
podemos ejecutar la función up
de todos los scripts en la carpeta ./migrations
con un state
de down
en la base de datos.
Para ejecutar la migración antes de que la aplicación comience, utilizamos scripts de npm. Los scripts de npm con un prefijo de pre
se ejecutarán antes que un script sin el prefijo pre
. Por ejemplo, si hay un script dev
y un script predev
, cada vez que se ejecute el script dev
con npm run dev
, el script predev
se ejecutará automáticamente antes de que se ejecute el script dev
.
Usaremos esta característica de los scripts de npm para colocar el comando ts-migrate-mongoose en un script prestart
para que la migración se ejecute antes del script start
.
Actualiza el archivo package.json
para tener un script prestart
que ejecute el comando ts-migrate-mongoose para ejecutar la función up
de los scripts de migración en el proyecto.
"scripts": {
"prestart": "npx migrate up",
"start": "node index.js"
},
Con esta configuración, cuando se ejecute npm run start
para iniciar la aplicación, el script prestart
se ejecutará para realizar la migración usando ts-migrate-mongoose y sembrar la base de datos antes de que la aplicación comience.
Deberías tener algo similar al fragmento a continuación después de ejecutar 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
Consulta la rama seed-users del repositorio para ver el estado actual de la base de código en este punto del artículo.
Cómo construir un endpoint de API para obtener datos sembrados
Podemos construir un endpoint de API para obtener los datos de usuarios sembrados en nuestra base de datos. En el archivo server.js
, actualiza el código al que se encuentra en el fragmento a continuación:
const { UserModel } = require("./user.model.js")
module.exports = async function (req, res) {
const users = await UserModel.find({}) // obtener todos los usuarios en la base de datos
res.writeHead(200, { "Content-Type": "application/json" });
return res.end(JSON.stringify({ // devolver una representación JSON de los datos de los usuarios obtenidos
users: users.map((u) => ({
email: u.email,
favouriteEmoji: u.favouriteEmoji,
yearOfBirth: u.yearOfBirth,
createdAt: u.createdAt
}))
}, null, 2));
};
Si iniciamos la aplicación y visitamos http://localhost:8000 usando Postman o un navegador, recibimos una respuesta JSON similar a la siguiente:
{
"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"
}
]
}
Nota que si la aplicación se ejecuta nuevamente, el script de migración ya no se ejecuta porque el estado
de la migración ahora será up
después de haber sido ejecutado con éxito.
Consulta la rama fetch-users del repositorio para ver el estado actual de la base de código en este punto del artículo.
Conclusión
Las migraciones son útiles al construir aplicaciones y hay necesidad de sembrar datos iniciales para pruebas, sembrar usuarios administrativos, actualizar el esquema de la base de datos añadiendo o eliminando columnas y actualizando los valores de columnas en muchos registros a la vez.
ts-migrate-mongoose puede ayudar a proporcionar un marco para ejecutar migraciones en tus aplicaciones de Node.js si usas Mongoose con MongoDB.
Source:
https://www.freecodecamp.org/news/handle-mongodb-migrations-with-ts-migrate-mongoose/