Resumen

Realizar operaciones equivalentes a un join en bases de datos NoSQL es posible gracias a lookup, la herramienta que ofrece MongoDB para relacionar documentos entre colecciones distintas. Comprender cuándo y cómo utilizarla marca la diferencia entre un diseño eficiente y un antipatrón que deteriora el rendimiento.

¿Por qué existen relaciones en MongoDB si es una base de datos NoSQL?

El paradigma NoSQL no elimina por completo las relaciones entre datos. Algunas bases de datos NoSQL, como las de grafos, manejan relaciones incluso más fuertes que SQL [0:22]. MongoDB, en cambio, maneja relaciones más débiles, pero igualmente útiles.

La diferencia fundamental radica en que SQL aplica reglas de normalización para estructurar esquemas, mientras que MongoDB prioriza la flexibilidad [0:52]. En lugar de normalización, MongoDB utiliza patrones de diseño que guían las mejores prácticas al modelar datos:

  • Patrones para relaciones uno a uno.
  • Patrones para relaciones uno a muchos.
  • Patrones para relaciones muchos a muchos.

Estos patrones permiten decidir cuándo conviene usar referencias entre colecciones y cuándo es mejor embeber los datos directamente en un documento [1:08].

¿Cuándo se convierte un lookup en un antipatrón?

Un punto clave es que utilizar más de tres lookups en una sola agregación ya se considera un antipatrón [1:33]. Esto significa que si tu consulta necesita cruzar muchas colecciones, probablemente el diseño del esquema necesita revisarse o quizás otra tecnología complementaría mejor la solución.

¿Cómo se construye un lookup paso a paso en MongoDB Compass?

Para el ejemplo práctico se utiliza la base de datos de películas que incluye MongoDB como muestra. Dentro de ella existe una colección llamada comments que contiene un campo movie_id, estableciendo una relación con el identificador de cada película [2:05].

Desde MongoDB Compass, dentro del pipeline de agregación, se agrega una primera etapa seleccionando lookup [1:53]. Los campos que se configuran son:

  • from: la colección con la que se quiere relacionar, en este caso comments.
  • localField: el campo local que sirve como referencia, aquí es _id.
  • foreignField: el campo foráneo en la otra colección, que corresponde a movie_id [2:25].
  • as: el nombre del nuevo campo donde aparecerán los resultados, por ejemplo comments.

Al ejecutar la etapa, cada documento de películas incorpora un array llamado comments con todos los comentarios asociados a ese identificador [2:42]. Algunas películas tendrán comentarios y otras mostrarán el array vacío.

¿Cómo combinar lookup con project en el pipeline?

La salida de una etapa siempre es la entrada de la siguiente. Esto permite encadenar un project después del lookup para mostrar únicamente los campos relevantes [3:05]:

  • El título de la película.
  • El nuevo campo comments generado por el lookup.

De esta forma se obtiene una vista limpia que muestra cada película junto con sus comentarios relacionados, sin la información innecesaria del resto del documento.

¿Cómo eliminar documentos relacionados con deleteMany?

Si tras revisar los resultados se identifica que ciertos comentarios no son relevantes, se pueden eliminar con deleteMany [3:42]. El comando se ejecuta directamente en la shell:

javascript db.comments.deleteMany({ movie_id: ObjectId("valor_del_identificador") })

Es importante recordar que se debe usar la palabra reservada ObjectId() con el valor del identificador entre paréntesis [4:02]. Este comando borra todos los comentarios cuyo movie_id coincida con el valor proporcionado.

Practicar con los datos de ejemplo que incluye MongoDB es una excelente forma de ganar soltura con estos comandos antes de aplicarlos en proyectos reales [4:18]. Experimenta combinando distintas etapas del pipeline y distintos comandos de escritura para afianzar tu comprensión.