Dominando las Operaciones CRUD de MongoDB: Una Guía Práctica de Comandos

Descubre el poder de MongoDB con esta guía práctica de comandos para las operaciones CRUD esenciales. Aprende a gestionar tus datos de manera eficiente usando los comandos `insert`, `find`, `update` y `delete`. Este artículo proporciona explicaciones claras, ejemplos del mundo real y mejores prácticas para crear, leer, actualizar y eliminar documentos en tus colecciones de MongoDB. Perfecto para desarrolladores y administradores, es tu recurso de referencia para dominar la manipulación de datos en MongoDB.

Dominando las Operaciones CRUD de MongoDB: Una Guía Práctica de Comandos

MongoDB, una popular base de datos NoSQL de documentos, forma la columna vertebral de innumerables aplicaciones modernas debido a su flexibilidad, escalabilidad y rendimiento. En el corazón de la interacción con cualquier base de datos se encuentran las operaciones fundamentales de Crear, Leer, Actualizar y Eliminar (CRUD). Dominar estos comandos es esencial para cualquiera que trabaje con MongoDB, desde desarrolladores que crean nuevas funciones hasta administradores que gestionan datos.

Esta guía utiliza una pequeña colección users y muestra los comandos CRUD de MongoDB que utilizas durante el trabajo real: agregar un registro desde un formulario de registro, encontrar el documento detrás de un ticket de soporte, cambiar un campo sin sobrescribir el resto del documento y eliminar datos sin borrar accidentalmente toda la colección. Los ejemplos usan mongosh, pero los mismos filtros y operadores de actualización se trasladan a los controladores de aplicaciones.

Prerrequisitos

Antes de sumergirte en los comandos, asegúrate de tener:

  • MongoDB instalado y ejecutándose: Puedes descargarlo desde el sitio web oficial de MongoDB o usar un servicio en la nube como MongoDB Atlas.
  • mongosh (Shell de MongoDB) instalado: Esta es la interfaz JavaScript interactiva para MongoDB.

Conectarse a MongoDB y Seleccionar una Base de Datos

Para comenzar, abre tu terminal o símbolo del sistema y conéctate a tu instancia de MongoDB usando mongosh:

mongosh

Una vez conectado, estarás en la base de datos test predeterminada. Para cambiar a una base de datos nueva o crearla, usa el comando use:

use myDatabase;

Si myDatabase no existe, MongoDB la creará implícitamente cuando insertes tu primer documento en una colección dentro de ella.

Operaciones de Creación (Insertar)

Las operaciones de creación implican agregar nuevos documentos a una colección. MongoDB proporciona métodos para insertar documentos individuales o múltiples.

1. db.collection.insertOne()

Este método inserta un solo documento en una colección. Si la colección no existe, MongoDB la crea.

// Seleccionar una colección llamada 'users'
db.users.insertOne({
  name: "Alice Smith",
  age: 30,
  city: "New York",
  email: "[email protected]",
  interests: ["reading", "hiking"]
});

La salida mostrará el estado acknowledged y el insertedId del nuevo documento.

2. db.collection.insertMany()

Usa este método para insertar múltiples documentos en una colección en una sola operación. Toma un array de documentos.

db.users.insertMany([
  {
    name: "Bob Johnson",
    age: 24,
    city: "Los Angeles",
    email: "[email protected]",
    interests: ["coding", "gaming"]
  },
  {
    name: "Charlie Brown",
    age: 35,
    city: "New York",
    email: "[email protected]",
    interests: ["cooking", "photography"]
  },
  {
    name: "Diana Prince",
    age: 29,
    city: "London",
    email: "[email protected]",
    interests: ["fitness", "travel"]
  }
]);

Esto devolverá un array de insertedIds para todos los documentos agregados.

Consejo: MongoDB agrega automáticamente un campo _id (un ObjectId único) a cada documento si no proporcionas uno.

Operaciones de Lectura (Buscar)

Las operaciones de lectura implican consultar documentos de una colección. El método find() es tu herramienta principal para esto.

1. db.collection.find()

a. Encontrar Todos los Documentos

Para recuperar todos los documentos en una colección, llama a find() sin argumentos:

db.users.find();

b. Encontrar Documentos con un Filtro de Consulta

Pasa un documento de consulta a find() para especificar criterios para seleccionar documentos. Esto actúa como una cláusula WHERE en SQL.

// Encontrar usuarios de New York
db.users.find({ city: "New York" });

// Encontrar usuarios mayores de 25 años
db.users.find({ age: { $gt: 25 } });

// Encontrar usuarios con edad entre 25 y 35 (excluyendo 35)
db.users.find({ age: { $gt: 25, $lt: 35 } });

// Encontrar usuarios cuyos intereses incluyan 'coding'
db.users.find({ interests: "coding" });

// Encontrar usuarios cuyos intereses incluyan TANTO 'reading' como 'hiking'
db.users.find({ interests: { $all: ["reading", "hiking"] } });

// Encontrar usuarios llamados Alice Smith O de Londres
db.users.find({
  $or: [
    { name: "Alice Smith" },
    { city: "London" }
  ]
});

Operadores de consulta comunes:

  • $eq: Igual a (predeterminado si no se especifica un operador)
  • $ne: No igual a
  • $gt: Mayor que
  • $gte: Mayor o igual que
  • $lt: Menor que
  • $lte: Menor o igual que
  • $in: Coincide con cualquiera de los valores especificados en un array
  • $nin: No coincide con ninguno de los valores especificados en un array
  • $and, $or, $not, $nor: Operadores lógicos

c. Proyección: Seleccionar Campos Específicos

Para devolver solo un subconjunto de campos, pasa un documento de proyección como segundo argumento a find(). Un valor de 1 incluye el campo, 0 lo excluye. El campo _id se incluye por defecto a menos que se excluya explícitamente.

// Devolver solo el nombre y el correo electrónico, excluir _id
db.users.find({ city: "New York" }, { name: 1, email: 1, _id: 0 });

d. Ordenar, Limitar y Saltar

Encadenar métodos permite consultas más complejas:

// Ordenar por edad en orden descendente (1 para ascendente, -1 para descendente)
db.users.find().sort({ age: -1 });

// Limitar resultados a 2 documentos
db.users.find().limit(2);

// Saltar los primeros 2 documentos y devolver el resto
db.users.find().skip(2);

// Combinar operaciones: Encontrar usuarios de New York, ordenar por edad, saltar 1, limitar 1
db.users.find({ city: "New York" }).sort({ age: 1 }).skip(1).limit(1);

2. db.collection.findOne()

Este método devuelve un solo documento que coincide con los criterios de consulta. Si varios documentos coinciden, devuelve el primero que encuentra.

db.users.findOne({ name: "Alice Smith" });

Operaciones de Actualización

Las operaciones de actualización modifican documentos existentes en una colección. Puedes actualizar un solo documento, varios documentos o incluso reemplazar un documento completo.

1. db.collection.updateOne()

Actualiza un solo documento que coincide con los criterios del filtro.

// Actualizar la ciudad de Alice a 'San Francisco'
db.users.updateOne(
  { name: "Alice Smith" },
  { $set: { city: "San Francisco", lastUpdated: new Date() } }
);

2. db.collection.updateMany()

Actualiza todos los documentos que coinciden con los criterios del filtro.

// Incrementar la edad de todos los usuarios en New York en 1
db.users.updateMany(
  { city: "New York" },
  { $inc: { age: 1 } }
);

// Agregar un nuevo interés 'reading' a los usuarios que aún no lo tienen
db.users.updateMany(
  {}, // Aplicar a todos los documentos
  { $addToSet: { interests: "reading" } }
);

// Eliminar 'gaming' de los intereses de Bob Johnson
db.users.updateOne(
  { name: "Bob Johnson" },
  { $pull: { interests: "gaming" } }
);

Operadores de actualización comunes:

  • $set: Establece el valor de un campo en un documento. Crea el campo si no existe.
  • $inc: Incrementa el valor de un campo en una cantidad especificada.
  • $unset: Elimina un campo de un documento.
  • $push: Agrega un valor a un campo de array.
  • $pull: Elimina todas las instancias de un valor o valores que coinciden con una consulta especificada de un array.
  • $addToSet: Agrega un valor a un array solo si el valor aún no está presente.

3. db.collection.replaceOne()

Reemplaza un solo documento que coincide con los criterios del filtro con un nuevo documento. El campo _id del documento que se reemplaza no se puede cambiar.

// Reemplazar completamente el documento de Bob Johnson
db.users.replaceOne(
  { name: "Bob Johnson" },
  {
    name: "Robert Johnson",
    occupation: "Software Engineer",
    status: "active",
    email: "[email protected]"
  }
);

Opción Upsert

Tanto updateOne() como updateMany() admiten una opción upsert. Si se establece en true y ningún documento coincide con el filtro, MongoDB insertará un nuevo documento basado en la consulta y las operaciones de actualización.

db.users.updateOne(
  { name: "David Lee" },
  { $set: { age: 28, city: "Seattle" } },
  { upsert: true } // Si David Lee no existe, créalo
);

Operaciones de Eliminación

Las operaciones de eliminación eliminan documentos de una colección. Ten mucho cuidado con las operaciones de eliminación, ya que son irreversibles.

1. db.collection.deleteOne()

Elimina como máximo un documento que coincida con el filtro especificado.

// Eliminar el usuario llamado 'Robert Johnson' (anteriormente 'Bob Johnson')
db.users.deleteOne({ name: "Robert Johnson" });

2. db.collection.deleteMany()

Elimina todos los documentos que coinciden con el filtro especificado.

// Eliminar todos los usuarios de Londres
db.users.deleteMany({ city: "London" });

Advertencia: Para eliminar todos los documentos en una colección, usa un filtro vacío {}. Ten mucho cuidado, ya que esta operación no se puede deshacer:

db.users.deleteMany({}); // Elimina todos los documentos en la colección 'users'

3. db.collection.drop()

Este método elimina permanentemente una colección completa de la base de datos, incluidos todos sus documentos e índices.

db.users.drop(); // Elimina toda la colección 'users'

Advertencia: Eliminar una colección es una operación altamente destructiva. Asegúrate de tener copias de seguridad adecuadas o estar absolutamente seguro antes de ejecutar este comando.

Mejores Prácticas para CRUD en MongoDB

  • Indexación: Para campos consultados con frecuencia, crea índices para acelerar significativamente las operaciones de lectura. db.collection.createIndex({ fieldName: 1 }).
  • Proyecciones: Solo recupera los datos que necesitas. Usar proyecciones ({ field: 1 }) reduce el ancho de banda de la red y el uso de memoria.
  • Operaciones por Lotes: Al insertar, actualizar o eliminar muchos documentos, usa insertMany(), updateMany() y deleteMany() en lugar de operaciones individuales para reducir la sobrecarga.
  • Comprender los Operadores: Familiarízate con el rico conjunto de operadores de consulta y actualización de MongoDB. Ofrecen formas poderosas de manipular tus datos.
  • Manejo de Errores: En una aplicación de producción, siempre implementa un manejo robusto de errores para tus operaciones de base de datos.
  • Diseño de Esquemas: Aunque MongoDB no tiene esquema, un diseño de esquema reflexivo es crucial para consultas eficientes y consistencia de datos.

Una Forma Más Segura de Practicar CRUD en una Base de Datos Real

La parte peligrosa de CRUD en MongoDB no es la sintaxis. Es ejecutar un filtro amplio en la base de datos incorrecta, especialmente con updateMany() o deleteMany(). Me gusta usar un hábito de tres pasos para cualquier escritura que toque datos existentes.

Primero, ejecuta el filtro como una lectura:

db.users.find(
  { city: "New York", status: "inactive" },
  { name: 1, email: 1, city: 1, status: 1 }
).limit(20);

Si la vista previa devuelve documentos que no esperabas, detente ahí. Arregla el filtro antes de pensar en la actualización. Si no devuelve nada, asegúrate de estar en la base de datos correcta con db.getName() y que los nombres de campo coincidan con los documentos reales.

Segundo, cuenta los documentos que coinciden:

db.users.countDocuments({ city: "New York", status: "inactive" });

Esto te da un radio de explosión aproximado. Si esperabas 12 usuarios y el recuento dice 12,000, el comando te está diciendo que algo está mal. Un recuento no es un sustituto de una copia de seguridad, pero es una barrera de seguridad económica.

Tercero, ejecuta la escritura con el comando más estrecho que se ajuste al trabajo. Usa updateOne() cuando un correo electrónico único, ID de cuenta o _id deba coincidir con un documento. Usa updateMany() solo cuando cambiar un segmento completo sea intencional.

db.users.updateMany(
  { city: "New York", status: "inactive" },
  {
    $set: {
      marketingEmailEnabled: false,
      updatedBy: "ops-maintenance-2025-11-04"
    }
  }
);

Agregar un updatedBy, updatedAt o una nota de mantenimiento no es requerido por MongoDB, pero ayuda más tarde cuando alguien pregunta por qué cambió un campo.

Errores Comunes que Causan Errores Reales

El primer error es reemplazar un documento cuando querías actualizar un campo. Este comando parece inofensivo, pero reemplaza todo el documento coincidente con solo los campos mostrados:

db.users.updateOne(
  { email: "[email protected]" },
  { city: "Boston" }
);

MongoDB moderno espera operadores de actualización para documentos de actualización a menos que estés usando métodos de estilo de reemplazo, por lo que este patrón puede fallar dependiendo del comando y la versión. El modelo mental más seguro es simple: si estás cambiando campos en su lugar, usa $set, $unset, $inc, $push, $pull u otro operador de actualización.

db.users.updateOne(
  { email: "[email protected]" },
  { $set: { city: "Boston" } }
);

El segundo error es consultar arrays como si el orden siempre importara. { interests: ["reading", "hiking"] } coincide con un array exactamente. { interests: "reading" } coincide con documentos donde el array contiene ese valor. { interests: { $all: ["reading", "hiking"] } } coincide con arrays que contienen ambos valores, independientemente del orden. Esas son tres preguntas diferentes.

El tercer error es asumir que findOne() devuelve "el correcto" cuando el filtro no es único. Si ejecutas:

db.users.findOne({ city: "New York" });

MongoDB devuelve un documento coincidente, pero sin una ordenación no debes tratar ese documento como el más nuevo, más antiguo, más importante o más representativo. Si el orden importa, dilo:

db.users.find({ city: "New York" }).sort({ createdAt: -1 }).limit(1);

El cuarto error es saltarse los índices hasta que la aplicación ya sea lenta. Una colección con unos pocos miles de documentos puede ocultar una consulta ineficiente. La misma consulta puede volverse dolorosa cuando la colección crece. Si la aplicación encuentra usuarios con frecuencia por email, crea un índice único cuando el modelo de datos lo permita:

db.users.createIndex({ email: 1 }, { unique: true });

Eso protege tanto el rendimiento como la calidad de los datos. Si ya existen correos electrónicos duplicados, el comando fallará, que es exactamente el tipo de problema que quieres descubrir antes de confiar en el correo electrónico como identificador.

Verificar lo que Realmente Hizo una Escritura

Los resultados de escritura de MongoDB valen la pena leerlos. Después de una actualización, mira matchedCount y modifiedCount. matchedCount te dice cuántos documentos coincidieron con el filtro. modifiedCount te dice cuántos se cambiaron realmente.

Si matchedCount es 1 y modifiedCount es 0, el comando puede estar bien. Quizás el campo ya tenía el valor solicitado. Si matchedCount es 0, tu filtro no coincidió con nada. Eso es común cuando un _id se pasa como una cadena en lugar de un ObjectId.

db.users.findOne({ _id: ObjectId("6650f1e59d0a41a37c2d8011") });

Para eliminaciones, verifica deletedCount. Si esperabas un documento eliminado y el resultado dice deletedCount: 0, no ejecutes inmediatamente una eliminación más amplia. Vuelve a verificar la base de datos, la colección y el filtro.

Cuando CRUD No es Suficiente

Los comandos CRUD básicos cubren la mayor parte del trabajo diario con datos, pero algunas tareas necesitan herramientas más potentes. Si estás actualizando varias colecciones que deben mantenerse consistentes juntas, mira las transacciones en conjuntos de réplicas o clústeres fragmentados. Si estás remodelando datos en muchos documentos, una canalización de agregación puede ser más clara que una larga serie de bucles del lado del cliente. Si estás migrando datos de producción, usa un script con registro, modo de prueba, copias de seguridad y un plan de reversión.

Para operaciones únicas en mongosh, mantén los comandos legibles. Una línea inteligente es más difícil de revisar y más difícil de recuperar. En producción, los comandos aburridos suelen ser mejores.

Los comandos CRUD de MongoDB son sencillos una vez que te acostumbras a los documentos, filtros y operadores de actualización. La habilidad que importa en el trabajo real es ser deliberado: previsualizar el filtro, contar el impacto, elegir el comando de escritura más estrecho, leer el resultado y dejar suficiente contexto para que la próxima persona pueda entender qué cambió.