Relaciones y uniones en Mongoose: cómo conectar tus modelos de MongoDB

Relaciones y uniones en Mongoose: cómo conectar tus modelos de MongoDB

¿Cómo realizar consultas entre uniones en Mongoose?

Populate en mongoose

Si bien no existen relaciones en las bases de datos NoSQL, podemos llevar acabo este proceso relacional a nivel del código de la aplicación. Mongoose provee una característica llamada population. Esta permite llenar ciertas partes del documento desde otra colección. Supongamos que tenemos las colecciones publicaciones y autores. Podemos agregar una referencia a las publicaciones desde el esquema de autores.

Populate en mongoose ejemplo

const mongoose = require("mongoose");

const autorSchema = mongoose.Schema({
    _id: Number,
    nombre: String,
    publicaciones: [
        {
            type: Schema.Types.ObjectId,
            ref: "Publicaciones",
        },
    ],
});

const publicacionSchema = mongoose.Schema({
    _autor: { type: Number, ref: "Autor" },
    titulo: String,
});

const Publicacion = mongoose.model("Publicacion", publicacionSchema);
const Autor = mongoose.model("Autor", autorSchema);

Autor.findOne({ name: "Gabriel Garcia Marquez" })
    .populate("publicaciones")
    .exec((err, autor) => {
        if (err) {
            console.log(err);
            process.exit(-1);
        }
        console.log(
            `Tl autor ${autor.nombre} tiene ${autor.publicaciones.length} publicaciones`
        );
    });

Los tipos de datos ObjectId, Number, String y Buffer son tipos validos para ser usados como referencias.

También es posible regresar solo una porción de los datos asociados ordenados por un campo en específico.

.populate({
    path: 'publicaciones',
    options: { limit: 10, sort: { titulo: 1 } }
})

Si se desea obtener solo ciertos campos de las colecciones asociadas.

.populate({
    path: 'publicaciones',
    select: '_id titulo', // separados por un espacio
    options: { limit: 10, sort: { titulo: 1 } }
})

Incluso se puede aplicar un filtro a los resultados.

.populate({
    path: 'publicaciones',
    select: '_id titulo',
    match: { titulo: /cien/i },
    options: { limit: 10, sort: { titulo: 1 } }
})

La mejor forma de realizar esta operación es utilizando select y eligiendo solo los campos requeridos. De esta forma se previene sobrecargar una consulta y retraer datos sensitivos dentro de esta.