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 la 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
Mezclado
ObjectId
Arreglo
Int32
Decimal128
Double
Map
Modelos
Los modelos toman su esquema y lo aplican a cada documento en su colección. Los modelos son responsables de todas las interacciones con documentos, como las operaciones de creación, lectura, actualización y eliminación (CRUD).
Tip
El primer argumento que pasas al modelo es la forma singular del nombre de tu colección. Mongoose cambia esto automáticamente a la forma plural, lo transforma a minúsculas y utiliza eso 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
Crea un esquema y modelo de Mongoose
Insertar, actualizar, buscar y borrar datos
Campos del documento del proyecto
Valida tus datos
Utiliza múltiples esquemas y middleware
Verificar los prerrequisitos
Antes de empezar este tutorial, asegúrate de tener preparados los siguientes componentes:
Una cuenta de MongoDB Atlas con un clúster configurado. Para ver las instrucciones, consulte MongoDB Get Started guía.
Node.js v16.20.1 o después.
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 utiliza módulos ES en lugar de CommonJS. Debes añadir el tipo module para usar módulos ES. Ve al archivo package.json y añade 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 marcado de posición <connection string> 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.
Crea un esquema y un modelo
Antes de empezar a agregar y actualizar datos en MongoDB, primero debes 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 datos, puedes editar directamente el objeto local con Mongoose. Luego, puedes usar el método save() para guardar 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 }
Buscar 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
Por defecto, las Mongoose queries devuelven "thenables", que son objetos con algunas propiedades de una JavaScript Promise. Puede agregar el método exec() a una query para recibir una verdadera JavaScript Promise. Para obtener más información sobre cómo trabajar con promesas en Mongoose, consulta 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.
Agrega el siguiente código a tu archivo index.js, reemplazando el marcador de posición <object
id> con el valor ObjectId del documento que has insertado previamente:
// 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 usa los métodos deleteOne() y deleteMany() para borrar datos de una colección. Puedes especificar el campo del documento que deseas borrar y pasar ese campo al método que elijas.
Agrega el siguiente código a tu archivo index.js para borrar 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 }
Valida tus datos
Los artículos insertados en los pasos anteriores no contienen los campos author, dates o comments, aunque estos campos estén incluidos en el esquema. Esto se debe a que, si bien ha definido la estructura de su documento, no ha definido qué campos son obligatorios. Se puede omitir cualquier campo que no se defina como obligatorio.
En Mongoose, cuando se incluye una validación en un campo, se 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 utilizar varios métodos de validación con Mongoose. Por ejemplo, puedes establecer required en verdadero en cualquier campo que desees hacer obligatorio. También puedes validar el tipo y el formato. En el siguiente código, el campo slug se define como un string con un minLength de 4. Esto significa que proporcionar un slug con menos de 4 caracteres resultará en un ValidationError.
Para agregar validación de datos y definir estos requerimientos, actualiza 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.
Introduce varios 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 archivo nuevo llamado User.js. Agregue 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:
Agrega
SchemaTypesa la lista de propiedades extraídas de la librería Mongoose.Cambia el campo
authortypeaSchemaTypes.ObjectIdy añade 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', });
Actualiza la llamada existente create() 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 añade una colección users con la colección blogs en la base de datos MongoDB. Este código agrega el campo requerido author y establece su valor en el 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, los middleware son funciones que se ejecutan antes o durante la ejecución de funciones asíncronas a nivel de esquema.
Un ejemplo de middleware es una función que valida el campo email de una instancia de User antes de guardar o actualizar.
Este ejemplo utiliza el paquete validator. Puedes instalar el paquete validator ejecutando el siguiente comando:
npm install validator
Para añadir esta función de middleware, añade el siguiente código a la declaración userSchema en tu 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 corriges la dirección de correo electrónico, puedes 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 tienes un proyecto de ejemplo que utiliza Mongoose para realizar operaciones CRUD en una colección de MongoDB. Desde aquí, puedes optar por compilar sobre este Proyecto con queries más complejas o validación de documentos. Las siguientes secciones incluyen algunos ejemplos de las funcionalidades de Mongoose que podría utilizar 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 a minúsculas los caracteres del campo blog.slug:
const blogSchema = new Schema({ ... slug: { type: String, required: true, minLength: 4, lowercase: true, }, ... });
Para más información, consulta la página de SchemaStringOptions en la documentación de la API de Mongoose.
Métodos asistentes
Mongoose incluye varios métodos asistentes que están abstraídos de los métodos regulares de MongoDB. En esta sección, puedes encontrar ejemplos de algunos de estos métodos. Estos métodos no se utilizan específicamente en este tutorial, pero son útiles para consultarlos cuando se comienza 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() permite encadenar y compilar consultas complejas.
Ejemplo de operación de búsqueda utilizando findOne() con un objeto de query simple y la query 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 de where() comienza con un findOne() que indica a Mongoose que lo trate como una query findOne(). Esto es importante porque si usas where() por sí solo (Blog.where(...)), Mongoose lo trata implícitamente como una operación find().
Generalmente, el método where() se utiliza para queries complejas que implican la creación dinámica de queries o múltiples comparadores, o cuando el uso de este método mejora la legibilidad. No existe diferencia de rendimiento entre utilizar el método where() o una query 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, consulta las siguientes secciones de la documentación de la API de Mongoose:
Recursos adicionales
Para aprender más sobre cómo utilizar Mongoose con MongoDB, consulta la Documentación de Mongoose.
Para encontrar soporte o contribuir a la comunidad de MongoDB, consulte la página de MongoDB Developer Community.