Node: Persistencia
Conoce cómo utilizar Node.js para conectarte a bases de datos, manejar la persistencia de datos y construir una API CRUD sólida. Configura drivers u ORMs y gestiona la información de forma eficaz en tus aplicaciones de JavaScript.
Aprende Node GRATIS y certifícateTrabajar con Node.js y bases de datos permite construir aplicaciones que guarden, consulten y actualicen información de forma ágil. Un enfoque común consiste en utilizar un modelo CRUD (Crear, Leer, Actualizar, Eliminar) para gestionar los datos y mantener la coherencia de la información.
La persistencia se refiere a almacenar los datos de manera que persistan incluso tras el reinicio de los servidores o la finalización de los procesos. Comprender cómo se logra esta persistencia en Node.js es esencial para desarrollar aplicaciones profesionales.
Selección de la base de datos
Existen opciones relacionales como MySQL o PostgreSQL, y opciones NoSQL como MongoDB. Cada sistema requiere un driver o librería que se encargue de la comunicación con el servidor de datos. Es recomendable elegir la base de datos acorde al tipo de datos y a las necesidades del proyecto.
Conexión con la base de datos
Para crear la conexión desde Node.js, se suele instalar el paquete oficial o una librería que facilite las operaciones con la base de datos. Por ejemplo, para MongoDB, se instala:
npm install mongodb
Si preferimos un enfoque de más alto nivel, se utiliza Mongoose:
npm install mongoose
En el caso de una base de datos relacional como MySQL, se instala:
npm install mysql2
Cada librería incluye métodos para iniciar la conexión y ejecutar consultas de forma asíncrona.
Configuración inicial
Al iniciar tu proyecto, es útil establecer variables de entorno en un archivo .env
que contenga datos confidenciales como la URL de conexión o credenciales de usuario. Un ejemplo de archivo .env
podría incluir:
DB_HOST=localhost
DB_USER=root
DB_PASS=claveSegura
DB_NAME=mi_base_datos
Para leer estos valores dentro de la aplicación, se instala la dependencia dotenv:
npm install dotenv
Después, se carga en el arranque del proyecto:
require('dotenv').config();
Este enfoque ayuda a mantener las credenciales seguras y facilita el despliegue en distintos entornos.
Creación de un modelo de datos
En aplicaciones basadas en MongoDB, se define un modelo con Mongoose:
const mongoose = require('mongoose');
const usuarioSchema = new mongoose.Schema({
nombre: String,
email: String,
edad: Number
});
module.exports = mongoose.model('Usuario', usuarioSchema);
Este esquema describe la estructura de los documentos en la colección y facilita las operaciones CRUD. Para bases de datos relacionales, se pueden crear entidades con un ORM como Sequelize, TypeORM u Objection.js, o bien escribir consultas SQL de forma manual.
Implementación de operaciones CRUD
- Crear (Create): Permite insertar nuevos registros en la base de datos.
- Leer (Read): Consulta datos existentes mediante filtros o peticiones específicas.
- Actualizar (Update): Modifica campos de registros previamente almacenados.
- Eliminar (Delete): Borra registros de la base para mantener la integridad de la información.
En Node.js, un ejemplo para Crear un nuevo usuario con Mongoose sería:
const Usuario = require('./Usuario');
async function crearUsuario(datos) {
const nuevoUsuario = new Usuario(datos);
return await nuevoUsuario.save();
}
El uso de async/await
en Node.js mejora la legibilidad del código y gestiona la asincronía de forma clara.
Rutas y controladores en una API
Para ofrecer un servicio CRUD sobre la entidad Usuario
, es habitual definir rutas HTTP en un archivo de controladores con Express:
const express = require('express');
const router = express.Router();
const Usuario = require('./Usuario');
// Crear
router.post('/usuarios', async (req, res) => {
try {
const usuarioCreado = await Usuario.create(req.body);
res.status(201).json(usuarioCreado);
} catch (error) {
res.status(400).json({ mensaje: 'Error al crear usuario' });
}
});
// Leer
router.get('/usuarios', async (req, res) => {
try {
const listaUsuarios = await Usuario.find();
res.json(listaUsuarios);
} catch (error) {
res.status(500).json({ mensaje: 'Error al obtener usuarios' });
}
});
// Actualizar
router.put('/usuarios/:id', async (req, res) => {
try {
const usuarioActualizado = await Usuario.findByIdAndUpdate(
req.params.id,
req.body,
{ new: true }
);
res.json(usuarioActualizado);
} catch (error) {
res.status(400).json({ mensaje: 'Error al actualizar usuario' });
}
});
// Eliminar
router.delete('/usuarios/:id', async (req, res) => {
try {
await Usuario.findByIdAndRemove(req.params.id);
res.json({ mensaje: 'Usuario eliminado' });
} catch (error) {
res.status(500).json({ mensaje: 'Error al eliminar usuario' });
}
});
module.exports = router;
Este ejemplo demuestra el uso de Express para manejar las peticiones y responde con un código de estado HTTP apropiado.
Buenas prácticas de persistencia de datos
- Validar los datos en el lado del servidor para evitar inconsistencias.
- Utilizar transacciones cuando la base de datos lo permita, especialmente en operaciones críticas.
- Seguir un patrón de capas que separe la lógica de negocio de las acciones de la base de datos.
- Asegurar la integridad y la coherencia de la información con índices y restricciones adecuadas.
- Monitorear la performance mediante herramientas de profiling y logs.
Manejo de errores y excepciones
Implementar bloque try/catch
en llamadas asíncronas y retornar respuestas adecuadas es esencial en aplicaciones productivas. Un servicio CRUD debe indicar al cliente cuándo una operación fracasa y por qué, manteniendo registro de cualquier excepción en archivos de log para futuras referencias.
Migraciones y versionado
En bases de datos relacionales, las migraciones son un recurso para actualizar la estructura de las tablas de manera controlada. En Node.js, se utilizan herramientas como Knex o Sequelize CLI para crear y ejecutar secuencias de migración que mantengan la coherencia de los esquemas en diferentes entornos.
Integración con microservicios
Los servicios CRUD son componentes esenciales en arquitecturas de microservicios. Un servicio responsable de la persistencia puede exponer una API y comunicarse con otros módulos de la aplicación, asegurando que cada microservicio cumpla una función específica y sea fácilmente escalable.
Uso de ORMs
Algunos proyectos eligen un ORM (Object-Relational Mapping) para reducir la complejidad al escribir consultas. Librerías como Sequelize, TypeORM y Mongoose (para MongoDB) dan la posibilidad de tratar la base de datos como objetos en JavaScript, simplificando operaciones y validaciones.
Lecciones de este módulo de Node
Lecciones de programación del módulo Persistencia del curso de Node.