Aprovecha lo mejor de Mongoose

Middlewares y Hooks de mongoose, un paso mas allá

En el desarrollo de aplicaciones grandes siempre hay que tomar en consideración una base de datos, y normalmente para facilitarnos el trabajo usamos ORM que nos quita el gran trabajo de estar pasando lo que tenemos guardado en una base de datos a estructuras para ser utilizadas en la aplicación. En este nuevo mundo de JavaScript, Node.js y base de datos NoSQL o no relacionales, la base de datos más utilizada es MongoDB, y su ORM por excelencia es Mongoose, y no solo por hacer un excelente trabajo, sino también por varias herramientas poderosas que ofrece, llamadas middlewares.

Los middlewares están basados en eventos que ocurren en el ciclo de vida de un documento dentro de una colección de mongo. Estos eventos son:

  • init: es el momento en el que hacemos un find, este es perfecto para cuando necesitamos datos calculados en caliente a partir de valores dentro del documento o para asignar valores por defecto dinámicamente.
  • validate: este evento se da cuando se aplican las reglas de validación que especificamos en el modelo o esquema, también es importante saber que este evento se da antes de save, y si no pasa la validación se aborta el evento save.
  • save: este es el evento en el cual se guarda el documento en la colección.
  • remove: éste es más obvio aún que save, este evento ocurre cuando se elimina un documento de la colección, este es perfecto para hacer cascadas de eliminación, cuando borramos un documento, borrar los demás documentos en distintas colecciones que hacen referencia a este.

Ademas de estos eventos, tenemos los “ganchos” o hooks, que es cuando podemos ejecutar las funciones que queramos que se ejecuten antes o después de cada uno de los eventos, y estos son pre y post respectivamente.

Entonces por ejemplo, suponiendo que queremos ejecutar una función antes de guardar un documento, esta sería de la siguiente manera:

const schema = new Schema(..); 
schema.pre(‘save’, (next) => {
// do stuff next();
});

Si quisiéramos ejecutar la función después de guardar en vez de antes, solo habria que cambiar el pre por post y listo, igualmente para los demás eventos.

Una de las principales diferencias entre los middlewares, además del momento en el que se ejecutan dependiendo del hook, es los parámetros que recibe el callback. Cuando el hook es pre los parámetros que recibe el callback son next y done, la diferencia entre estos es que done se pasa cuando se desea hacer una ejecución en paralelo después de llamar a next, como en el siguiente caso:

const schema = new Schema(..); 
// `true` means this is a parallel middleware.
// You **must** specify `true`
// as the second parameter if you want to use parallel middleware.
schema.pre(‘save’, true, (next, done) => { 
// calling next kicks off the next middleware in parallel next();
setTimeout(done, 100);
});

El `next`al igual que en express, puede ser utilizado para el manejo de errores.

schema.pre(‘save’, (next) => {
// You **must** do `new Error()` or
// `next(‘something went wrong’)` will
// **not** work
const err = new Error(‘something went wrong’);
next(err);
});

Cuando el hook es post, el callback recibe doc y next, next es usado solamente cuando se quiere ejecutar código asíncrono.

schema.post(‘init’, (doc) => {
console.log(‘%s has been initialized from the db’, doc._id);
});
schema.post(‘validate’, (doc) => {
console.log(‘%s has been validated (but not saved yet)’, doc._id);
});
schema.post(‘save’, (doc) => {
console.log(‘%s has been saved’, doc._id);
});
schema.post(‘remove’, (doc) => {
console.log(‘%s has been removed’, doc._id);
});

Esto es todo, cualquier pregunta, no duden en comentar y si les gustó o lo encontraron útil, compartan o recomienden. También se aceptan ideas para los próximos post.

Show your support

Clapping shows how much you appreciated Luis Fuenmayor’s story.