Overview
Mongoose es una librería de Modelado de Datos de Objetos (ODM) para MongoDB. Puedes usar Mongoose para facilitar el modelado de datos, la aplicación del esquema, la validación de modelos y la manipulación general de datos. Como MongoDB tiene un modelo de datos flexible que te permite modificar y actualizar bases de datos en el futuro, no hay esquemas rígidos. Sin embargo, Mongoose aplica un esquema semi rígido desde el principio, por lo que se debe definir un esquema y un modelo.
Schemas
Un esquema define la estructura de los documentos de su colección. Un esquema de Mongoose se asigna directamente a una colección de MongoDB.
El siguiente ejemplo crea un nuevo esquema llamado blog:
const blog = new Schema({ title: String, slug: String, published: Boolean, author: String, content: String, tags: [String], comments: [{ user: String, content: String, votes: Number }] }, { timestamps: true });
Al crear un esquema, debe definir cada campo y sus tipos de datos. Se permiten los siguientes tipos:
String
Número
fecha
Buffer
Booleano
Mixto
ObjectId
Arreglo
Int32
Decimal128
Double
Map
Modelos
Los modelos toman su esquema y lo aplican a cada documento de su colección. Son responsables de todas las interacciones con los documentos, como las operaciones de creación, lectura, actualización y eliminación (CRUD).
Tip
El primer argumento que se pasa al modelo es la forma singular del nombre de la colección. Mongoose lo cambia automáticamente a plural, lo convierte a minúsculas y lo usa para el nombre de la colección de la base de datos.
El siguiente ejemplo muestra cómo declarar un modelo llamado Blog que utiliza el esquema blog:
const Blog = mongoose.model('Blog', blog);
En el ejemplo anterior, Blog se traduce a la colección blogs en MongoDB.
Tutorial
En este tutorial, realizarás las siguientes acciones:
Configura tu entorno para usar Mongoose
Conéctese a MongoDB
Crear un esquema y un modelo de Mongoose
Insertar, actualizar, buscar y eliminar datos
Campos del documento del proyecto
Validar sus datos
Utilice múltiples esquemas y middleware
Verificar los prerrequisitos
Antes de comenzar este tutorial, asegúrese de tener los siguientes componentes preparados:
Una cuenta de MongoDB Atlas con un clúster configurado. Para ver las instrucciones, consulte Guíade introducción a MongoDB.
Node.js 1620v..1 o posterior.
Configura tu entorno
Este tutorial usa nodemon para ejecutar el código localmente. Ejecute los siguientes comandos en su terminal para inicializar su proyecto e instalar las dependencias necesarias:
mkdir mongodb-mongoose cd mongodb-mongoose npm init -y npm i mongoose npm i -D nodemon
Abre tu proyecto en tu editor de código preferido. Este tutorial usa módulos ES en lugar de CommonJS. Debes agregar el tipo module para usar módulos ES. Ve al archivo package.json y agrega el siguiente código:
... "scripts": { "dev": "nodemon index.js" }, "type": "module", ...
Inicie su aplicación con nodemon ejecutando el siguiente comando:
npm run dev
Nota
Cuando usas nodemon, el código se ejecuta cada vez que guardas un archivo.
Conéctese a MongoDB
En el nivel raíz de tu proyecto, crea un archivo llamado index.js y añade el siguiente código al principio del archivo:
import mongoose from 'mongoose'; mongoose.connect("<connection string>")
Reemplace el <connection string> marcador con su cadena de conexión de MongoDB Atlas. Para obtener más información sobre cómo encontrar su cadena de conexión, consulte el tutorial "Conectarse a su clúster" en la documentación de Atlas.
Crear un esquema y un modelo
Antes de comenzar a agregar y actualizar datos en MongoDB, debe crear un esquema y un modelo.
Con Mongoose, creas un archivo de modelo de esquema para cada esquema que se necesite. Primero, cree una carpeta llamada model para guardar todos los archivos de su esquema y, luego, cree su primer archivo de esquema llamado Blog.js. Abre este archivo y añade el siguiente código:
import mongoose from 'mongoose'; const { Schema, model } = mongoose; const blogSchema = new Schema({ title: String, slug: String, published: Boolean, author: String, content: String, tags: [String], comments: [{ user: String, content: String, votes: Number }] }, { timestamps: true }); const Blog = model('Blog', blogSchema); export default Blog;
Este esquema permite una opción timestamps que añade los campos createdAt y updatedAt gestionados por mongoose al esquema, los cuales se actualizan automáticamente. Para obtener más información, consulta la página de Sello de tiempo en la documentación de Mongoose.
Realizar operaciones CRUD
Ahora que tienes tu primer modelo y esquema configurados, puedes empezar a insertar datos en la base de datos. Las siguientes secciones muestran cómo realizar operaciones CRUD utilizando Mongoose.
Insert Data
Vaya a index.js y agregue la siguiente declaración de importación en la parte superior de su archivo:
import Blog from './model/Blog.js';
Agregue el siguiente código debajo de la línea que contiene su cadena de conexión:
// Creates a new blog post and inserts it into database const article = await Blog.create({ title: 'Awesome Post!', slug: 'awesome-post', published: true, content: 'This is the best post ever', tags: ['featured', 'announcement'], }); console.log('Created article:', article);
El código anterior utiliza el método Mongoose create() para crear el objeto que representa un artículo de blog y luego lo guarda en la base de datos. El documento devuelto se registra en la consola, incluyendo su _id. Toma nota de este _id para usarlo en futuros pasos.
Actualizar datos
Para actualizar los datos, puede editar directamente el objeto local con Mongoose. Luego, puede usar el método save() para escribir la actualización en la base de datos.
Agregue el siguiente código para actualizar el artículo que insertó en la sección anterior:
// Updates the title of the article article.title = "The Most Awesomest Post!!"; await article.save(); console.log('Updated Article:', article);
Updated Article: { title: 'The Most Awesomest Post!!', slug: 'awesome-post', published: true, content: 'This is the best post ever', tags: [ 'featured', 'announcement' ], _id: new ObjectId('...'), comments: [], __v: 0 }
Encontrar datos
Para encontrar un documento específico, puede utilizar el método Mongoose findById() para consultar un documento especificando su _id.
Agregue el siguiente código a su archivo index.js para encontrar un artículo específico por su _id:
// Finds the article by its ID. Replace <object id> with the objectId of the article. const articleFound = await Blog.findById("<object id>").exec(); console.log('Found Article by ID:', articleFound);
Found Article by ID: { _id: new ObjectId('68261c9dae39e390341c367c'), title: 'The Most Awesomest Post!!', slug: 'awesome-post', published: true, content: 'This is the best post ever', tags: [ 'featured', 'announcement' ], comments: [], __v: 0 }
Nota
De forma predeterminada, las consultas de Mongoose devuelven thenables, que son objetos con algunas propiedades de una promesa de JavaScript. Puede añadir el exec() método a una consulta para obtener una promesa de JavaScript verdadera. Para obtener más información sobre cómo trabajar con promesas en Mongoose, consulte la guía de promesas en la documentación de Mongoose.
Especificar campos del documento
Puede usar Mongoose para proyectar solo los campos que necesita. El siguiente código especifica que solo se proyecten los campos title, slug y content.
Agregue el siguiente código a su archivo index.js, reemplazando el marcador de posición <object
id> con el valor ObjectId del documento que insertó anteriormente:
// Finds the article by its ID and projects only the title, slug, and content fields. // Replace <object id> with the objectId of the article. const articleProject = await Blog.findById("<object id>", "title slug content").exec(); console.log('Projected Article:', articleProject);
Projected Article: { _id: new ObjectId('...'), title: 'The Most Awesomest Post!!', slug: 'awesome-post', content: 'This is the best post ever' }
Eliminar datos
Mongoose utiliza los métodos deleteOne() y deleteMany() para eliminar datos de una colección. Puede especificar el campo del documento que desea eliminar y pasarlo al método que elija.
Agregue el siguiente código a su archivo index.js para eliminar un artículo de la base de datos:
// Deletes one article with the slug "awesome-post". const blogOne = await Blog.deleteOne({ slug: "awesome-post" }); console.log('Deleted One Blog:', blogOne);
Deleted One Blog: { acknowledged: true, deletedCount: 1 }
Para eliminar varios artículos, puede agregar el siguiente código:
// Deletes all articles with the slug "awesome-post". const blogMany = await Blog.deleteMany({ slug: "awesome-post" }); console.log('Deleted Many Blogs:', blogMany);
Deleted Many Blogs: { acknowledged: true, deletedCount: 4 }
Validar sus datos
Los artículos insertados en los pasos anteriores no contienen los campos author, dates ni comments, aunque estos estén incluidos en el esquema. Esto se debe a que, si bien definió la estructura de su documento, no ha definido qué campos son obligatorios. Cualquier campo que no esté definido como obligatorio puede omitirse.
En Mongoose, cuando incluye la validación en un campo, debe pasar un objeto como su valor.
Nota
Los validadores se ejecutan automáticamente en los métodos create() y save(). Puedes especificar que se ejecuten en métodos de actualización, como update() y updateOne(), configurando la opción runValidators en true. Para obtener más información sobre los validadores, consulta la página Validación en la documentación de Mongoose.
Puedes usar varios métodos de validación con Mongoose. Por ejemplo, puedes establecer required como verdadero en cualquier campo que desees que sea obligatorio. También puedes validar el tipo y el formato. En el siguiente código, el campo slug se define como string con un minLength de 4. Esto significa que proporcionar un slug con menos de 4 caracteres resultará en un ValidationError.
Para agregar la validación de datos y definir estos requisitos, actualice el esquema en Blog.js como se muestra en el siguiente ejemplo:
const blogSchema = new Schema({ title: { type: String, required: true, }, slug: { type: String, required: true, minLength: 4, }, published: { type: Boolean, default: false, }, author: { type: String, required: true, }, content: String, tags: [String], comments: [{ user: String, content: String, votes: Number }] }, { timestamps: true });
Después de añadir esta validación, su aplicación se bloqueará. Agregue un campo author a la llamada create() en su archivo index.js para cumplir con el nuevo requisito de validación:
// Creates a new blog post and inserts it into database const article = await Blog.create({ title: 'Awesome Post!', slug: 'awesome-post', published: true, author: 'A.B. Cee', content: 'This is the best post ever', tags: ['featured', 'announcement'], });
Tip
Cuando usas esquemas con Mongoose, value: String es igual que value: {type: String}.
Para obtener más información, consulte la página Validación en la documentación de Mongoose.
Introducir múltiples esquemas
A continuación, puedes agregar más complejidad a tu campo author creando otro esquema e incluyéndolo en el esquema del blog.
En la carpeta model, crea un nuevo archivo llamado User.js. Agrega el siguiente código a este archivo:
import mongoose from 'mongoose'; const {Schema, model} = mongoose; const userSchema = new Schema({ name: { type: String, required: true, }, email: { type: String, minLength: 10, required: true, lowercase: true }, }); const User = model('User', userSchema); export default User;
Para utilizar su nuevo modelo de usuario para definir el campo author en el esquema del blog, actualice el archivo Blog.js con los siguientes cambios:
Agregue
SchemaTypesa la lista de propiedades extraídas de la biblioteca Mongoose.Cambie el campo
authortypeaSchemaTypes.ObjectIdy agregue una referencia (ref) al modelo'User'.
El siguiente código muestra estas actualizaciones:
const { Schema, SchemaTypes, model } = mongoose; ... // Inside Schema block: author: { type: SchemaTypes.ObjectId, ref: 'User', required: true, }, ...
Puede reutilizar el mismo modelo User para el campo comment.user cambiando la definición blogSchema:
... // Inside Schema block: comments: [{ user: { type: SchemaTypes.ObjectId, ref: 'User', required: true, }, ...
Para usar el nuevo modelo de usuario en su aplicación, vaya al archivo index.js. Agregue el siguiente código al principio del archivo para importar el modelo de usuario:
import User from './model/User.js';
Debido a que agregó la validación de campo al esquema del blog, el código anterior para insertar, actualizar y eliminar blogs, y para especificar campos para proyectar, no pasará la validación y la aplicación generará un error.
Cree un nuevo usuario agregando la siguiente llamada create():
// Create a new user const user = await User.create({ name: 'Jess Garica', email: 'jgarcia@email.com', });
Actualice la llamada create() existente con el siguiente código para crear un nuevo artículo que utilice al nuevo usuario como autor, como se muestra en el siguiente código:
// Creates a new blog post that references the user as the author const articleAuthor = await Blog.create({ title: 'Awesome Post!', slug: 'Awesome-Post', author: user._id, content: 'This is the best post ever', tags: ['featured', 'announcement'], }); console.log('Article with Author:', articleAuthor);
Article with Author: { title: 'Awesome Post!', slug: 'awesome-post', published: false, author: new ObjectId('...'), content: 'This is the best post ever', tags: [ 'featured', 'announcement' ], _id: new ObjectId('...'), createdAt: 2025-05-15T18:05:23.780Z, comments: [], __v: 0 }
El código anterior agrega una colección users a la colección blogs en la base de datos MongoDB. Este código agrega el campo obligatorio author y establece su valor en user._id.
Para añadir los valores de los campos name y email al campo author del artículo, puede adjuntar el método populate() de Mongoose a su consulta de Blog. El método populate() realizará una segunda query para el documento de Usuario referido por user._id.
Agregue el siguiente código a index.js para completar estos datos:
// Populates the author field with user data const articlePopulate = await Blog.findOne({ title: "Awesome Post!" }).populate("author"); console.log('Article Populated:', articlePopulate);
Article Populated: { _id: new ObjectId('...'), title: 'Awesome Post!', slug: 'awesome-post', published: false, author: { _id: new ObjectId('...'), name: 'Jess Garica', email: 'jgarcia@email.com', __v: 0 }, content: 'This is the best post ever', tags: [ 'featured', 'announcement' ], createdAt: 2025-05-15T18:04:28.590Z, comments: [], __v: 0 }
Para obtener más información, consulte la página Document.populate() de la documentación de la API de Mongoose.
Agregar middleware
En Mongoose, el middleware son funciones que se ejecutan antes o durante la ejecución de funciones asincrónicas en el nivel de esquema.
Un ejemplo de middleware es una función que valida el campo email de una instancia User antes de guardar o actualizar.
Este ejemplo utiliza el paquete validator. Puede instalar el paquete validator ejecutando el siguiente comando:
npm install validator
Para agregar esta función de middleware, agregue el siguiente código a la declaración userSchema en su archivo User.js:
import validator from 'validator';
userSchema.pre('save', function (next) { const user = this; // Normalize email if (user.email) { user.email = user.email.trim().toLowerCase(); } // Validate email format if (!validator.isEmail(user.email)) { return next(new Error('Invalid email format')); } next(); });
Para ver el efecto de esta función, modifica el campo user.email en tu archivo index.js para convertirlo en una dirección de correo electrónico no válida:
const user = await User.create({ name: 'Jess Garica', email: 'jgarciaemail.com', });
Error: Invalid email format
Si corrige la dirección de correo electrónico, podrá ver que no se produce el error.
Además de la pre() función de middleware, Mongoose también ofrece la post() función. Para más información sobre middleware, consulte la página de middleware en la documentación de Mongoose.
Próximos pasos
Ahora tiene un proyecto de ejemplo que usa Mongoose para realizar operaciones CRUD en una colección de MongoDB. A partir de aquí, puede optar por desarrollar este proyecto con consultas más complejas o validación de documentos. Las siguientes secciones incluyen algunos ejemplos de funciones de Mongoose que podría usar en su aplicación.
Setters personalizados de Mongoose
Los setters personalizados modifican tus datos cuando se guardan y pueden implementarse de manera similar a los validadores. Mongoose proporciona los siguientes setters personalizados:
lowercaseuppercasetrim
El siguiente ejemplo convierte en minúsculas los caracteres en el campo blog.slug:
const blogSchema = new Schema({ ... slug: { type: String, required: true, minLength: 4, lowercase: true, }, ... });
Para obtener más información, consulte la página SchemaStringOptions en la documentación de la API de Mongoose.
Métodos auxiliares
Mongoose incluye varios métodos auxiliares que se derivan de los métodos estándar de MongoDB. En esta sección, encontrará ejemplos de algunos de estos métodos. Estos métodos no se utilizan específicamente en este tutorial, pero son útiles como referencia para comenzar a usar Mongoose.
existe()
El método exists() devuelve null o el primer documento que coincide con la query proporcionada. El siguiente es un ejemplo de coincidencia de un artículo en función del campo author:
const blog = await Blog.exists({ author: 'Jess Garcia' }); console.log(blog);
Para obtener más información, consulte la sección Model.exists() de la documentación de la API de Mongoose.
dónde()
El método where() le permite encadenar y crear consultas complejas.
El siguiente es un ejemplo de cómo realizar una operación de búsqueda utilizando findOne() con un objeto de consulta simple y la consulta equivalente con el método where():
const blogFind = await Blog.findOne({ author: "Jess Garcia" }); console.log(blogFind); const blogWhere = await Blog.findOne().where("author").equals("Jess Garcia"); console.log(blogWhere);
En esta implementación, la implementación where() comienza con un findOne() que indica a Mongoose que la trate como una consulta findOne(). Esto es importante porque si se usa where() solo (Blog.where(...)), Mongoose la trata implícitamente como una operación find().
Generalmente, el método where() se utiliza para consultas complejas que implican la creación dinámica de consultas o comparadores múltiples, o cuando su uso mejora la legibilidad. No hay diferencia de rendimiento entre usar el método where() y una consulta de objeto simple.
Para incluir la proyección al utilizar el método where(), encadene el método select() después de su query, como se muestra en el siguiente ejemplo:
const blog = await Blog.findOne().where("author").equals("Jess Garcia").select("title author"); console.log(blog);
Para obtener más información, consulte las siguientes secciones de la documentación de la API de Mongoose:
Recursos adicionales
Para obtener más información sobre el uso de Mongoose con MongoDB, consulte la documentación de Mongoose.
Para encontrar ayuda o contribuir a la comunidad MongoDB, consulte la página de la Comunidad de desarrolladores de MongoDB.