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 $match en 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() y db.collection.stats()

Comparación de MongoDB con Otras Bases de Datos

CaracterísticaMongoDBPostgreSQLMySQLRedis
Modelo de datosDocumentos (JSON)Relacional (tablas)Relacional (tablas)Clave-valor / estructuras de datos
EsquemaFlexible (sin esquema)Estricto (SQL DDL)Estricto (SQL DDL)Sin esquema
Lenguaje de consultaMQL + AgregaciónSQLSQLComandos
Joins$lookup (limitado)Joins SQL completosJoins SQL completosNinguno
TransaccionesACID multi-documentoACID completoACID completoAtómico por operación
EscaladoHorizontal (sharding)Vertical (+ read replicas)Vertical (+ read replicas)En memoria, horizontal
Ideal paraEsquemas flexibles, desarrollo ágilConsultas complejas, integridad de datosAplicaciones web, WordPressCaché, 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, updateOne y deleteOne con 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 mongodump y prueba las restauraciones con mongorestore — 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

Artículos Relacionados