MongoDB es una base de datos NoSQL orientada a documentos que almacena los datos como documentos JSON flexibles en lugar de filas y columnas. Mientras que las bases de datos relacionales exigen definir un esquema de antemano y reestructurar las tablas cuando cambian los requisitos, MongoDB permite que cada documento de una colección tenga campos distintos, lo que lo hace ideal para aplicaciones donde las estructuras de datos evolucionan rápidamente. Esta guía cubre la instalación de MongoDB, las operaciones CRUD fundamentales, estrategias de indexación y la configuración de replica sets para entornos de producción.
Requisitos Previos
- Un servidor Linux (Ubuntu 22.04 o RHEL 8+ recomendado) con al menos 2 GB de RAM
- Acceso root o sudo para la instalación
- Comprensión básica del formato de datos JSON
- Familiaridad con herramientas de línea de comandos
Instalación de MongoDB
Ubuntu/Debian
# Importar la clave GPG de MongoDB
curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | \
sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor
# Añadir el repositorio
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] \
https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | \
sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list
# Instalar MongoDB
sudo apt update
sudo apt install -y mongodb-org
# Iniciar y habilitar el servicio
sudo systemctl start mongod
sudo systemctl enable mongod
# Verificar que está en ejecución
sudo systemctl status mongod
mongosh --eval "db.version()"
RHEL/CentOS
# Crear el archivo de repositorio
cat <<'EOF' | sudo tee /etc/yum.repos.d/mongodb-org-7.0.repo
[mongodb-org-7.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/7.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-7.0.asc
EOF
sudo dnf install -y mongodb-org
sudo systemctl start mongod
sudo systemctl enable mongod
Docker
docker run -d \
--name mongodb \
-p 27017:27017 \
-v mongodb-data:/data/db \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=secretpassword \
mongo:7
Operaciones CRUD Básicas
Conéctate a MongoDB usando el shell:
# Conectarse a MongoDB local
mongosh
# Conectarse a un servidor remoto con autenticación
mongosh "mongodb://admin:password@192.168.1.100:27017/admin"
Create — Insertar Documentos
// Cambiar a (o crear) una base de datos
use myapp
// Insertar un único documento
db.users.insertOne({
name: "Alice Johnson",
email: "alice@example.com",
role: "admin",
skills: ["python", "docker", "kubernetes"],
created: new Date()
})
// Insertar múltiples documentos
db.users.insertMany([
{ name: "Bob Smith", email: "bob@example.com", role: "developer", skills: ["javascript", "react"] },
{ name: "Carol Lee", email: "carol@example.com", role: "devops", skills: ["terraform", "aws", "docker"] }
])
MongoDB crea la base de datos y la colección automáticamente al insertar el primer documento — no se necesita CREATE TABLE ni CREATE DATABASE.
Read — Consultar Documentos
// Obtener todos los documentos de una colección
db.users.find()
// Buscar con un filtro
db.users.find({ role: "admin" })
// Consultar campos anidados y arrays
db.users.find({ skills: "docker" }) // El array contiene "docker"
db.users.find({ "skills.0": "python" }) // La primera habilidad es "python"
// Operadores de comparación
db.users.find({ age: { $gt: 25 } }) // Mayor que
db.users.find({ role: { $in: ["admin", "devops"] } }) // Dentro del array
// Proyección — seleccionar campos específicos
db.users.find({ role: "admin" }, { name: 1, email: 1, _id: 0 })
// Ordenar y limitar
db.users.find().sort({ created: -1 }).limit(10)
// Contar documentos
db.users.countDocuments({ role: "developer" })
Update — Modificar Documentos
// Actualizar un documento
db.users.updateOne(
{ email: "alice@example.com" },
{ $set: { role: "superadmin", lastLogin: new Date() } }
)
// Añadir un elemento a un array
db.users.updateOne(
{ email: "bob@example.com" },
{ $push: { skills: "typescript" } }
)
// Actualizar múltiples documentos
db.users.updateMany(
{ role: "developer" },
{ $set: { department: "engineering" } }
)
// Upsert — actualiza si existe, inserta si no
db.users.updateOne(
{ email: "dave@example.com" },
{ $set: { name: "Dave Wilson", role: "intern" } },
{ upsert: true }
)
Delete — Eliminar Documentos
// Eliminar un documento
db.users.deleteOne({ email: "dave@example.com" })
// Eliminar múltiples documentos
db.users.deleteMany({ role: "intern" })
// Eliminar una colección completa
db.users.drop()
Indexación para el Rendimiento
Sin índices, MongoDB realiza un escaneo completo de la colección — lee cada documento para encontrar coincidencias. En una colección con millones de documentos, esto puede tardar segundos en lugar de milisegundos.
// Crear un índice de campo único
db.users.createIndex({ email: 1 }) // Ascendente
// Crear un índice compuesto (múltiples campos)
db.users.createIndex({ role: 1, created: -1 })
// Crear un índice único (garantiza unicidad)
db.users.createIndex({ email: 1 }, { unique: true })
// Crear un índice de texto para búsqueda full-text
db.articles.createIndex({ title: "text", body: "text" })
db.articles.find({ $text: { $search: "mongodb tutorial" } })
// Listar todos los índices de una colección
db.users.getIndexes()
// Analizar una consulta para ver si usa un índice
db.users.find({ email: "alice@example.com" }).explain("executionStats")
Reglas generales para la indexación:
- Indexa los campos usados en filtros de
find(),sort(), y$matchen agregaciones - En índices compuestos, ordena los campos del más selectivo al menos selectivo
- Evita indexar campos con baja cardinalidad (por ejemplo, campos booleanos con solo
true/false) - Cada índice consume RAM — monitoriza con
db.stats()ydb.collection.stats()
Comparación de MongoDB con Otras Bases de Datos
| Característica | MongoDB | PostgreSQL | MySQL | Redis |
|---|---|---|---|---|
| Modelo de datos | Documentos (JSON) | Relacional (tablas) | Relacional (tablas) | Clave-valor / estructuras de datos |
| Esquema | Flexible (sin esquema) | Estricto (SQL DDL) | Estricto (SQL DDL) | Sin esquema |
| Lenguaje de consulta | MQL + Agregación | SQL | SQL | Comandos |
| Joins | $lookup (limitado) | Joins SQL completos | Joins SQL completos | Ninguno |
| Transacciones | ACID multi-documento | ACID completo | ACID completo | Atómico por operación |
| Escalado | Horizontal (sharding) | Vertical (+ read replicas) | Vertical (+ read replicas) | En memoria, horizontal |
| Ideal para | Esquemas flexibles, desarrollo ágil | Consultas complejas, integridad de datos | Aplicaciones web, WordPress | Caché, sesiones, tiempo real |
Pipeline de Agregación
El pipeline de agregación es la respuesta de MongoDB a las consultas SQL complejas con GROUP BY, JOIN y subconsultas:
// Contar usuarios por rol
db.users.aggregate([
{ $group: { _id: "$role", count: { $sum: 1 } } },
{ $sort: { count: -1 } }
])
// Encontrar las habilidades más frecuentes entre todos los usuarios
db.users.aggregate([
{ $unwind: "$skills" },
{ $group: { _id: "$skills", count: { $sum: 1 } } },
{ $sort: { count: -1 } },
{ $limit: 10 }
])
// Unir usuarios con sus pedidos (como un JOIN en SQL)
db.orders.aggregate([
{ $lookup: {
from: "users",
localField: "userId",
foreignField: "_id",
as: "user"
}},
{ $unwind: "$user" },
{ $project: { orderTotal: 1, "user.name": 1, "user.email": 1 } }
])
Copia de Seguridad y Restauración
# Hacer backup de una base de datos específica
mongodump --db myapp --out /backup/$(date +%Y-%m-%d)
# Backup con autenticación
mongodump --uri="mongodb://admin:password@localhost:27017" --db myapp --out /backup/
# Backup de todas las bases de datos
mongodump --out /backup/full-$(date +%Y-%m-%d)
# Restaurar una base de datos
mongorestore --db myapp /backup/2025-12-13/myapp
# Restaurar eliminando primero los datos existentes
mongorestore --drop --db myapp /backup/2025-12-13/myapp
Casos Extremos y Comportamientos Inesperados
Límite de tamaño de documento: Un documento MongoDB no puede superar los 16 MB. Si necesitas almacenar archivos grandes, usa GridFS — la especificación de MongoDB para almacenar archivos de más de 16 MB distribuidos en múltiples documentos.
Sin joins por defecto: Aunque $lookup ofrece funcionalidad básica de join, es más lento que los joins relacionales. Diseña el esquema de documentos para embeber datos relacionados dentro de un único documento cuando sea posible (desnormalización).
Write concern y pérdida de datos: Por defecto, MongoDB confirma las escrituras cuando llegan al primario. Si el primario cae antes de la replicación, los datos se pierden. Para datos críticos, usa writeConcern: { w: "majority" } para esperar la replicación.
ObjectId no es secuencial: El campo _id predeterminado de MongoDB usa ObjectId, que codifica un timestamp pero no es estrictamente secuencial. No uses el orden de _id como sustituto de un campo de timestamp created.
Almacenamiento mapeado en memoria: El motor WiredTiger de MongoDB usa la RAM disponible para caché. Un servidor con 8 GB de RAM y una base de datos de 100 GB solo almacena en caché el conjunto de trabajo activo. Monitoriza las tasas de acierto de caché con db.serverStatus().wiredTiger.cache.
Solución de Problemas
MongoDB no arranca
# Revisar el log en busca de errores
sudo journalctl -u mongod --no-pager -n 50
# Causa frecuente: espacio en disco insuficiente o permisos incorrectos
ls -la /var/lib/mongodb/
sudo chown -R mongodb:mongodb /var/lib/mongodb
Consultas lentas
// Usa explain para verificar si las consultas usan índices
db.users.find({ email: "alice@example.com" }).explain("executionStats")
// Busca "COLLSCAN" en la salida — significa que no se usa ningún índice
// Crea un índice en el campo consultado
db.users.createIndex({ email: 1 })
Conexión rechazada desde clientes remotos
# MongoDB escucha en localhost por defecto
# Edita /etc/mongod.conf para permitir conexiones remotas
# net:
# bindIp: 0.0.0.0 # Escuchar en todas las interfaces
# IMPORTANTE: ¡Habilita la autenticación primero!
sudo systemctl restart mongod
Resumen
- MongoDB almacena documentos similares a JSON en colecciones sin requerir un esquema predefinido — cada documento puede tener campos distintos, lo que lo hace ideal para estructuras de datos cambiantes
- Las operaciones CRUD usan métodos intuitivos como
insertOne,find,updateOneydeleteOnecon filtros de consulta en JSON en lugar de SQL - Los índices son fundamentales para el rendimiento — crea índices en los campos usados en consultas y operaciones de ordenación, y usa
explain()para verificar su uso - El pipeline de agregación gestiona transformaciones de datos complejas, agrupaciones y joins que en SQL requerirían GROUP BY y JOIN
- Haz copias de seguridad regularmente con
mongodumpy prueba las restauraciones conmongorestore— un backup que no has probado no es un backup - Diseña los documentos para embeber datos relacionados en lugar de normalizar entre colecciones — esto reduce la necesidad de costosos joins con
$lookup