MongoDB desde cero: documentos, colecciones y el cambio del modelo NoSQL
MongoDB desde cero: documentos, colecciones y el cambio del modelo NoSQL
Introducción
Si estás dando tus primeros pasos en el mundo del desarrollo de software, seguramente ya habrás escuchado hablar de bases de datos y, muy probablemente, de SQL. Las bases de datos relacionales (como MySQL, PostgreSQL o SQLite) son las que más se estudian en las aulas y las que la mayoría usamos en proyectos pequeños. Sin embargo, en los últimos años ha surgido un modelo alternativo: las bases de datos NoSQL.
MongoDB es uno de los representantes más populares de este enfoque. A diferencia de una tabla con filas y columnas, MongoDB guarda la información en documentos similares a JSON, organizados en colecciones. Esta estructura permite modelar datos de forma mucho más flexible, una característica que resulta esencial cuando trabajás con requisitos cambiantes, datos no estructurados o aplicaciones que necesitan escalar horizontalmente.
En este artículo, vamos a explicar MongoDB desde cero. Veremos qué son un documento y una colección, cómo crearlos, realizar operaciones CRUD básicas y, lo más importante, entender por qué el modelo NoSQL representa un cambio en la forma de pensar los datos en comparación con las bases de datos relacionales. Todo esto acompañado de ejemplos prácticos con la salida esperada, para que podás seguirlos sin perderte.
El contenido está orientado a desarrolladores back‑end, estudiantes de ingeniería o ciencia de datos, y a cualquier persona que quiera comprender los fundamentos de MongoDB antes de adentrarse en casos de uso más complejos.
¿Qué es MongoDB?
MongoDB es un almacén de datos NoSQL orientado a documentos. En lugar de almacenar datos en tablas con filas y columnas fijas, MongoDB guarda cada registro como un documento BSON (Binary JSON). BSON es una extensión binaria de JSON que permite un rango más amplio de tipos de datos (por ejemplo, fechas, objetos binarios, decimales, etc.).
Documentos vs Filas
| Característica | Base de datos relacional (SQL) | MongoDB (NoSQL) |
|---|---|---|
| Estructura | Esquema fijo, columnas predefinidas | Sin esquema previo, cada documento puede tener campos distintos |
| Relaciones | Normalización mediante claves foráneas | Incorporación (embedding) o referencias (referencing) |
| Escalabilidad | Escala vertical (añadir más recursos a un servidor) | Escala horizontal (agregar más nodos fácilmente) |
| Consulta | SQL (JOINs, GROUP BY, etc.) | Consultas basadas en JSON, operadores potentes |
Colecciones
Una colección en MongoDB es análoga a una tabla en SQL, pero con una diferencia clave: puede contener documentos de diferentes formas. Imagina una colección users donde algunos documentos tienen campos como nombre, email, edad, mientras que otros también incluyen dirección, teléfono, etc. Todos coexisten sin necesidad de alterar un esquema preexistente.
Configuración rápida del entorno (opcional)
Si querés experimentar con MongoDB localmente, podés instalar el paquete oficial desde mongodb.com/try/download/community. Una vez instalado, el comando mongosh te da acceso a la shell de MongoDB. Para los ejemplos de este artículo no es estrictamente necesario tener un servidor en ejecución; los comandos se muestran junto con la salida esperada, para que podás visualizar cómo se verían.
Si preferís un enfoque sin instalar nada, tenés la opción de usar MongoDB Atlas (el servicio gestionado en la nube de MongoDB) y crear una cuenta gratuita. Los mismos comandos de la shell funcionarán.
Creación de una base de datos y una colección
Una base de datos en MongoDB es un contenedor lógico para colecciones, similar a un esquema en SQL. No creas una base de datos físicamente hasta que insertas el primer documento.
Ejemplo: Crear la base de datos ecommerce y la colección products
// En la shell de MongoDB (mongosh)
use ecommerceSalida esperada:
switched to db ecommerceuse ecommerce selecciona (o crea) la base de datos ecommerce. Ahora podés comenzar a crear documentos en la colección products:
db.products.insertMany([
{
"productId": "p001",
"name": "Laptop Pro",
"category": "Electronics",
"price": 1499.99,
"stock": 30,
"tags": ["laptop", "computer", "work"],
"specs": {
"cpu": "Apple M2",
"ram": "16GB",
"storage": "512GB SSD"
}
},
{
"productId": "p002",
"name": "Organic Avocado",
"category": "Grocery",
"price": 2.5,
"stock": 200,
"tags": ["fruit", "healthy", "organic"],
"specs": {
"origin": "California",
"weight": "150g"
}
}
])Salida esperada (vista al ejecutar db.products.find().pretty()):
{
"_id": ObjectId("60d5ecf5f2e5c93b2d5e4e5c"),
"productId": "p001",
"name": "Laptop Pro",
"category": "Electronics",
"price": 1499.99,
"stock": 30,
"tags": ["laptop", "computer", "work"],
"specs": {
"cpu": "Apple M2",
"ram": "16GB",
"storage": "512GB SSD"
}
}
{
"_id": ObjectId("60d5f0b5f2e5c93b2d5e4e5d"),
"productId": "p002",
"name": "Organic Avocado",
"category": "Grocery",
"price": 2.5,
"stock": 200,
"tags": ["fruit", "healthy", "organic"],
"specs": {
"origin": "California",
"weight": "150g"
}
}Cada documento recibe automáticamente un _id único (ObjectId), que es fundamental para la identidad del documento.
Documentos en MongoDB: más allá del JSON
El uso de BSON permite a MongoDB almacenar una variedad de tipos de datos que van un poco más allá del JSON estándar:
| Tipo JSON | Tipo BSON equivalente |
|---|---|
| string | String |
| number | Int32 / Int64 / Double |
| boolean | Boolean |
| null | Null |
| array | Array |
| object | Document (embed) |
| date | Date |
| binary | BinData (para archivos) |
Por qué es importante el uso de BSON
- Rendimiento: El formato binario reduce el espacio de almacenamiento y acelera las serializaciones.
- Tipos adicionales: Puedes guardar fechas, valores decimales o inclusalmente objetos JavaScript (
code,symbol). - Ordenación y consultas: Algunos tipos, como
date, permiten ordenar directamente en la base de datos.
Ejemplo: Insertar un documento con tipos de datos avanzados
db.users.insertOne({
"username": "jdoe",
"fullName": "John Doe",
"isActive": true,
"loginCount": NumberInt(42),
"balance": NumberDecimal("123.45"),
"joinedAt": ISODate("2022-08-15T10:30:00Z"),
"avatar": BinData(0, "VGhpcyBpcyBhIHRlc3QgYmluYXJ5IGlkAA=="),
"roles": ["admin", "editor"],
"profile": {
"bio": "Desarrollador apasionado",
"preferences": {
"theme": "dark",
"notifications": true
}
}
})Salida esperada (db.users.findOne()):
{
"_id": ObjectId("60d5f2c5f2e5c93b2d5e4e5e"),
"username": "jdoe",
"fullName": "John Doe",
"isActive": true,
"loginCount": 42,
"balance": 123.45,
"joinedAt": ISODate("2022-08-15T10:30:00Z"),
"avatar": BinData(0, "..."),
"roles": ["admin", "editor"],
"profile": {
"bio": "Desarrollador apasionado",
"preferences": {
"theme": "dark",
"notifications": true
}
}
}Operaciones CRUD básicas
Aprender MongoDB sin pasar por las operaciones CRUD resultaría incompleto. A continuación, detallamos cada una de ellas con un ejemplo concreto y la salida esperada.
1. Crear (Insertar)
La operación insertOne agrega un único documento; insertMany acepta un array y crea varios.
db.tasks.insertOne({
"title": "Diseñar prototipo",
"status": "pending",
"priority": 3,
"tags": ["UX", "UI"]
})Salida esperada:
{
"acknowledged": true,
"insertedId": ObjectId("60d5f4c5f2e5c93b2d5e4e5f")
}2. Leer (Consultar)
Consulta simple
db.tasks.findOne({ "title": "Diseñar prototipo" })Salida esperada: (lo mismo que insertaste, con el _id agregado)
Consulta con proyección (solo ciertos campos)
db.tasks.find(
{ "status": "pending" },
{ "title": 1, "status": 1, "_id": 0 }
).pretty()Salida esperada:
{ "title": "Diseñar prototipo", "status": "pending" }Uso de operadores
db.tasks.find({
"priority": { "$gte": 3 },
"tags": "UX"
}).pretty()Salida esperada: mostrará cualquier documento que cumpla con priority mayor o igual a 3 y que tenga "UX" dentro del array tags.
3. Actualizar
updateOne modifica el primer documento que coincida; updateMany modifica todos los documentos coincidentes.
db.tasks.updateOne(
{ "title": "Diseñar prototipo" },
{ "$set": { "status": "in-progress", "priority": 1 } }
)Salida esperada:
{
"acknowledged": true,
"matchedCount": 1,
"modifiedCount": 1,
"upsertedId": null
}4. Eliminar
db.tasks.deleteOne({ "title": "Diseñar prototipo" })Salida esperada:
{
"acknowledged": true,
"deletedCount": 1
}Incorporación vs Referencia: Diseño de esquemas
Una de las decisiones más importantes al trabajar con MongoDB es decidir cómo modelar relaciones entre entidades. Los dos enfoques predominantes son:
- Incorporación (Embedding): Guardar documentos relacionados dentro de otro documento.
- Referencia (Referencing): Guardar una copia del
_idde otro documento y mantener ese documento en una colección separada.
Cuándo incorporar
- Relación uno a muchos donde el documento hijo cambia raramente.
- El hijo es pequeño, y se accede a él frecuentemente junto con el padre.
- El padre define el contexto (por ejemplo, un
ordercon susitems).
Cuándo referenciar
- El documento hijo es grande y cambia regularmente.
- Hay muchos padres que comparten el mismo hijo (muchos a muchos).
- Es importante mantener la integridad referencial (aunque MongoDB no aplica claves foráneas de forma nativa, se puede simular).
Ejemplo: Modelo de blog con incorporación
db.posts.insertOne({
"title": "Introducción a MongoDB",
"author": "alice",
"content": "MongoDB es genial...",
"comments": [
{
"user": "bob",
"text": "¡Excelente artículo!",
"likes": 5
},
{
"user": "carla",
"text": "Muy claro.",
"likes": 2
}
]
})Salida esperada: se inserta un post con dos comentarios integrados.
Ejemplo: Modelo de blog con referencia
// Primero, crear la colección `comments`
db.comments.insertMany([
{
"_id": ObjectId("60d5f6c5f2e5c93b2d5e4e60"),
"user": "bob",
"text": "¡Excelente artículo!",
"likes": 5
},
{
"_id": ObjectId("60d5f7c5f2e5c93b2d5e4e61"),
"user": "carla",
"text": "Muy claro.",
"likes": 2
}
])
// Luego, el post hace referencia a ellos
db.posts.insertOne({
"title": "Introducción a MongoDB",
"author": "alice",
"content": "MongoDB es genial...",
"commentIds": [
ObjectId("60d5f6c5f2e5c93b2d5e4e60"),
ObjectId("60d5f7c5f2e5c93b2d5e4e61")
]
})Salida esperada: el post incluye un array commentIds con los ObjectIds referenciados.
Nota: Aunque referenciar añade complejidad de consulta (necesitas
$lookuppara uniones), suele ser más flexible para esquemas en evolución.
Por qué el modelo NoSQL cambia el enfoque de los datos
1. Sin esquema previo
En SQL, typically definís un CREATE TABLE con columnas y tipos fijos. Cambiar ese esquema puede requerir migraciones costosas. MongoDB, en cambio, permite agregar nuevos campos a documentos existentes sin interrupción.
2. Documentos ricos y semiestructurados
Pensá en una aplicación móvil que recibe datos de múltiples fuentes: JSON de APIs externas, logs con campos variables, sensores con lecturas aleatorias. Guardar todo en documentos BSON evita tener que Normalizar datos en múltiples tablas.
3. Escalado horizontal y tolerancia a fallos
nativo
MongoDB está diseñado para ejecución en clústeres replicados. Cada nodo mantiene una copia de los datos, lo que permite escribir en cualquier nodo (con replicación de escrituras) y leer desde el más cercano. Esto contrasta con el escalado vertical tradicional de bases de datos relacionales, que se ve limitado por los recursos de un único servidor.
4. CAP y consistencia eventual
El teorema CAP (Coherencia, Disponibilidad, Tolerancia a particiones) nos dice que un sistema distribuido puede garantizar a lo sumo dos de estos tres aspectos. MongoDB prioriza Consistencia (mediante replicación) y Disponibilidad, pero sacrifica estrictamente la coherencia en escenarios de alta partition. Esto se conoce como consistencia eventual — los lectores pueden ver datos desactualizados por un breve período.
5. Consultas ricas y operadores
Los operadores de consulta de MongoDB permiten realizar filtrados complejos directamente en el servidor, como $regex, $elemMatch, $text, $geoNear. No necesitas escribir uniones SQL o subconsultas; podés expresar lógica en el propio JSON.
6. Flexibilidad en el desarrollo ágil
Cuando los requisitos cambian rápidamente (por ejemplo, un producto necesita agregar un nuevo campo a un perfil de usuario), con SQL necesitarías alterarlos en tiempo de ejecución. Con MongoDB, podés simplemente insertar documentos con ese nuevo campo, y la aplicación seguirá funcionando.
Casos de uso donde MongoDB destaca
| Caso de uso | Por qué MongoDB es una buena opción |
|---|---|
| Big Data & Analytics | Puede almacenar logs no estructurados, eventos de clickstream y datos de sensores en un solo sitio. Los potentes agregadores ($group, $project) aceleran la obtención de insights. |
| Administración de contenido (CMS) | Contenido variado (imágenes, vídeos, markdown, metadatos) se guarda como documentos flexibles. Sin necesidad de múltiples tablas para diferentes tipos de contenido. |
| Aplicaciones móviles / IoT | Datos en tiempo real de dispositivos, a menudo en JSON. MongoDB puede procesarlos cerca del origen con bajo retardo. |
| Microservicios | Cada servicio puede tener su propia colección, reduciendo acoplamiento. No es necesario gestionar esquemas centralizados. |
| Dashboards en tiempo real | Los cambios se reflejan rápidamente gracias a replicación y operados como $currentDate. Las consultas pueden filtrarse por rangos de tiempo. |
Buenas prácticas y recomendaciones
1. Diseña campos consistentes
- Utiliza camelCase o snake_case de forma consistente en toda la colección.
- Evita guardar arrays de documentos que nunca vas a consultar juntos; en su lugar, considera incorporar o referenciar.
2. Crear índices para las consultas frecuentes
db.users.createIndex({ "email": 1 })
db.orders.createIndex({ "status": 1, "createdAt": -1 })Los índices aceleran las búsquedas, pero consumen espacio. Utilízalos con moderación.
3. Validación de esquemas (opcional pero útil)
Puedes usar schemaValidation a nivel de colección para asegurarse de que los documentos cumplan reglas (por ejemplo, price debe ser un número positivo).
db.products.createCollection("products", {
validator: {
$and: [
{ "price": { $type: "double", $gte: 0 } },
{ "name": { $type: "string", $maxLength: 100 } }
]
}
})4. Controla el tamaño de los documentos
MongoDB tiene un límite de documento de 16 MB. Si necesitas algo más grande, considera dividir en múltiples documentos (por ejemplo, con shardKey).
5. Utiliza $inc, $push, $pull para actualizaciones atómicas
db.inventory.updateOne(
{ "productId": "p001" },
{ "$inc": { "stock": -1 } }
)Esto evita condiciones de carrera en aplicaciones concurrente.
6. Aprovecha la paginación
Siempre devuelve una subconjunto de resultados con limit y skip (o cursor.batchSize). Para grandes volúmenes de datos, considera find().cursor.batchSize(20).
Errores comunes y cómo evitarlos
| Error | Por qué sucede | Cómo solucionarlo |
|---|---|---|
| Sobrealimentar un índice | Creación indiscriminada de índices sin entender las consultas reales. | Revisa las estadísticas de db.collection.stats() y db.collection.aggregate([... { $indexStats: {} }]). |
| Guardar demasiados datos en un documento | Sobrecargar el almacenamiento o rebasar los 16 MB. | Divide en documentos más pequeños, usa subcolecciones (mediante prefijo en nombres) o referencia. |
Ignorar el _id de ObjectId |
Pensar que es solo un identificador, no un timestamp. | Utiliza $expr o agregación para extraer fecha de creación si es necesario. |
| Consultas sin índice que causan escaneo de colección | Al inicio, las aplicaciones a menudo consultan con campos sin índice. | Monitorea explain() para ver el plan de ejecución. |
| Uso incorrecto de incorporación vs referencia | Incorporar todo por simplicidad, pero luego los documentos se vuelven inmanejables. | Reevalúa las cardinalidades de relaciones; haz un modelo híbrido. |
Resumen y próximos pasos
MongoDB ofrece una alternativa potente y flexible a las bases de datos relacionales. Al almacenar datos en documentos BSON dentro de colecciones, podés modelar información semiestructurada sin necesidad de un esquema fijo. Las operaciones CRUD básicas (insert, find, update, delete) son intuitivas y se expresan en JavaScript, lo que alinea el lenguaje de consulta con el lenguaje de programación.
Entender las diferencias conceptuales — documentos vs filas, incorporación vs referencia, y la filosofía NoSQL de escalado horizontal — te ayuda a decidir cuándo MongoDB es la mejor opción. Los casos de uso típicos abarcan desde aplicaciones web modernas y gestión de contenido hasta analítica de big data e IoT.
Si querés profundizar, podrías explorar:
- Shardings y particionamiento para manejar conjuntos de datos masivos.
- Aggregations para pipeline de procesamiento de datos complejos.
- MongoDB Atlas para usar un clúster gestionado sin preocuparte por la infraestructura.
- Mecanismos de seguridad como RBAC, encryption-at-rest y TLS.
Con una base sólida en documentos, colecciones y los principios que hacen diferente a NoSQL, estás listo para comenzar a construir aplicaciones escalables y flexibles con MongoDB. ¡Feliz modelado!
Referencias útiles
- Documentación oficial de MongoDB – referencia completa de APIs y ejemplos.
- MongoDB University – cursos gratuitos y certificaciones.
- The MongoDB Handbook – guía práctica para diseñadores y desarrolladores de sistemas.
Sobre el autor
Soy un desarrollador back‑end con más de 10 años de experiencia construyendo sistemas de datos a escala. Me apasiona ayudar a otros a entender conceptos complejos de bases de datos a través de explicaciones prácticas y codebases reales. Si tenés preguntas, sugerencias o un caso de uso específico que te gustaría que cubra, no dudes en contactarme.
DUGLAS MORENO
Comentarios (0)
Sé el primero en comentar.