Técnicas simples para realizar operaciones de unión en MongoDB
Simple techniques for performing join operations in MongoDB.
Introducción
Las personas que trabajan con bases de datos están muy familiarizadas con los JOINS. Cuando queremos obtener datos de varias tablas, a menudo unimos las tablas en función de las claves primarias y las claves extranjeras. En este artículo aprenderemos técnicas simples para realizar operaciones de unión en MongoDB.

El diagrama anterior es una representación pictórica del esquema de base de datos relacional de cualquier organización. Esos bloques son tablas que almacenan tipos particulares de datos (estudiantes/profesores/empleados) y las líneas y flechas representan la relación entre las tablas utilizando claves comunes. Podemos realizar uniones entre las tablas en función de las relaciones entre ellas.
Por ejemplo, en una organización, hay tablas separadas para almacenar los datos de los empleados, departamentos, proyectos, etc., donde los datos se almacenan de manera normalizada. Para obtener los detalles de los empleados y en qué departamento y proyecto trabajan, necesitamos realizar una unión entre las tablas y obtener los datos necesarios.
Nuevamente, en una universidad, puede haber tablas separadas para almacenar los datos de los estudiantes y profesores. Para averiguar qué profesores enseñan a un estudiante en particular, necesitamos realizar una unión entre las tablas.
Objetivo de aprendizaje
En este tutorial particular, veremos cómo realizar diferentes operaciones de unión (unión interna, unión externa, unión derecha y unión izquierda) en MongoDB.
- Dos técnicas avanzadas de SQL que pueden mejorar drásticamente tus ...
- ¿En qué se diferencian los cyborgs de la inteligencia artificial?
- Las Mejores Plataformas para Encontrar Trabajos en Inteligencia Art...
Este artículo se publicó como parte de la Blogatón de Ciencia de Datos.
Comprendiendo los diferentes tipos de operaciones de unión comunes
A. SQL y diferentes tipos de uniones
La mayoría de nosotros tenemos conocimientos sobre bases de datos SQL. Allí a menudo realizamos cuatro tipos principales de uniones, que discutiremos a continuación.
1. Unión interna: Solo habrá filas con claves comunes de ambas tablas en la tabla resultante.


Como podemos ver, después de realizar las uniones internas, solo se devolvieron las filas donde la clave Número de rol es común en ambas.
2. Unión externa izquierda: Todas las filas de la tabla izquierda (claves coincidentes + claves no coincidentes) estarán en la tabla resultante. Por lo tanto, en la tabla resultante solo habrá filas de claves coincidentes de la tabla derecha; no se pueden eliminar todas las filas donde las claves no coincidan.

Después de realizar la unión izquierda, tenemos todas las columnas de la tabla izquierda. Dado que el Rango de clase para Deepak K. no está presente en la tabla derecha, se rellena con nulo. Como se discutió, solo los registros de la tabla derecha que coinciden con el Número de rol de la tabla izquierda están presentes en los resultados. Por esa razón, la tupla (3D5RE, 16) de la tabla derecha no está en el resultado.
3. Unión externa derecha: Es lo opuesto a la unión externa izquierda. Aquí todas las filas de la tabla derecha estarán en la tabla resultante y solo habrá filas con claves coincidentes de la tabla izquierda.

Como era de esperar, todos los registros/tuplas de la tabla derecha están presentes en el resultado, pero el registro (2A3AS, Deepak K., 87) de la tabla izquierda está ausente.
4. Unión completa (Full Outer Join): Todas las filas de ambas tablas (claves coincidentes + claves no coincidentes) estarán presentes en la tabla resultante.

Como era de esperar, tenemos todas las tuplas de ambas tablas en nuestro resultado. Los lugares donde no hay valores están llenos con null.
B. Introducción breve a MongoDB
MongoDB es una base de datos NoSQL basada en documentos. Las bases de datos NoSQL son mejores para almacenar datos a gran escala, no relacionales, no estructurados y que cambian con frecuencia. Los siguientes dos blogs contienen comparaciones y operaciones en MongoDB.
- Introducción a MongoDB
- Operaciones CRUD en MongoDB
La base de datos de MongoDB consiste en una o más colecciones. Las colecciones se pueden considerar equivalentes a las tablas en las bases de datos SQL. Cada colección consiste en uno o más documentos. Por lo tanto, los documentos se pueden considerar como filas o tuplas de una tabla en bases de datos SQL. Los datos se almacenan en formato BSON (JSON binario) dentro de MongoDB.

Operación de unión en MongoDB
Ahora veamos cómo se realizan las diferentes operaciones de unión en las colecciones de MongoDB.
Convierte las dos tablas Marks y Rank en colecciones, donde cada tupla se convierte en un documento de las respectivas colecciones. Almacena las colecciones en una base de datos llamada School en MongoDB.


Unión externa izquierda (Left Outer Join)
Código:
db.Marks.aggregate([{$lookup:{from:"Rank",localField:"Roll No",
foreignField:"Roll No",as:"Ranks"}}])

[Ampliar salida]
Como podemos ver, los detalles de la clasificación del estudiante respectivo se agregan a su documento. Para Deepak, no hay detalles de clasificación en la tabla Rank, por lo que obviamente su campo Ranks es una lista vacía.
Ahora comprendamos los parámetros utilizados:
- Aquí, Marks es nuestra tabla izquierda.
- $lookup es la función/operador de agregación para realizar una unión en dos colecciones.
- En el método lookup, from denota la colección con la que queremos realizar la unión, es decir, nuestra tabla derecha (colección). En nuestro caso, Rank es nuestra colección derecha.
- localField denota la clave de la colección izquierda que se comparará con la clave de la colección derecha para realizar la unión. Si se encuentra una clave coincidente en el campo de la colección derecha, el campo resultante (aquí Ranks) no está vacío; de lo contrario, está vacío (como en el caso de Deepak en nuestro ejemplo).
- foreignField es la clave de la colección derecha.
- as denota el nombre del nuevo campo que se formará en la tabla/colección resultante debido a la unión, donde se almacenarán los detalles de la tabla derecha (colección).
- En nuestro caso, se agrega el nuevo campo Ranks a la tabla/colección resultante que contiene los detalles de las clasificaciones de los estudiantes correspondientes.
Una cosa a tener en cuenta, en MongoDB $lookup solo puede realizar joins izquierdos y no hay una sintaxis específica disponible para otros tipos de joins. Por lo tanto, necesitamos derivar los otros joins utilizando diferentes trucos y operaciones
Join externo derecho (Right Outer Join)
Ahora, el join derecho es justo lo opuesto al join izquierdo, donde además de los registros coincidentes, los registros no coincidentes de la colección/tabla derecha también deben estar presentes en la colección/tabla resultante.
Una forma sencilla de hacerlo es simplemente alterar la posición de las dos colecciones; entonces nuestra colección derecha se convierte en la izquierda y viceversa. Ahora, el join contendrá todas las filas (coincidentes + no coincidentes) de nuestra tabla derecha.
Código :
db.Rank.aggregate([{$lookup:{from:"Marks", localField:"Roll No",
foreignField:"Roll No", as:"Marks_Students"}}])
[Ampliar resultado]
Join interno (Inner Join)
¡Podemos realizar eficientemente un join interno con un simple truco! Haremos un join izquierdo y luego eliminaremos todos esos registros donde el campo as está vacío. Así que solo nos quedaremos con los registros donde las claves están presentes en ambas tablas (colecciones).
Código :
db.Rank.aggregate([{$lookup:{from:"Marks", localField:"Roll No", foreignField:"Roll No",
as: "Marks_Students"}}, {$match:{"Marks_Students":{$ne:[]}}}])

[Ampliar resultado]
Como podemos ver en el resultado anterior, solo tenemos los registros para los cuales las claves de ambas colecciones coincidieron. Aquí {$match:{“Marks_Students”:{$ne:[]}}} indica que coincida solo con aquellos registros donde el campo Marks_Students no está vacío
Join externo completo (Full Outer Join)
El join externo completo es un poco complicado, lo diseñé mediante una combinación de 3 operaciones. Así que si se ve confuso a primera vista, te pido que lo leas varias veces para entenderlo mejor.
Paso 1: Haremos un join izquierdo de Marks (colección izquierda) y Rank (colección derecha) y agregaremos un campo vacío llamado Marks a todos los registros resultantes y enviaremos/sacaremos el resultado en una nueva colección llamada J2.
Código:
db.Marks.aggregate([{$lookup:{from:"Rank",localField:"Roll No", foreignField:"Roll No", as:"Rank"}},
{$addFields:{Marks:[]}},{$out:"J2"}])

[Ampliar resultado]
Entonces, nuestra nueva colección se ve como la captura de pantalla anterior.
- {$addFields:{Marks:[]}} -> agrega un campo extra llamado Marks a todos los registros.
- {$out:“J2″}] -> envía/saca el resultado a una nueva colección J2.
Entonces ahora, como es obvio, nuestra base de datos School contiene 3 colecciones-
Marks, Rank, J2

Paso 2: Realizaremos la unión correcta (como se discutió antes considerando Rango como la colección izquierda) de Notas y Rango y agregaremos el resultado a la colección J2.
Código:
db.Rango.aggregate([{$lookup:{from:"Notas",localField:"Número de matrícula",foreignField:"Número de matrícula",
as:"Notas"}},{$merge:"J2"}])

[Ampliar salida]

[Ampliar salida]
Observa cómo el sistema agrega la nueva salida al final de la antigua salida del paso 1.
Paso 3:
Solo mantendremos los registros en nuestro resultado de agregación donde el campo Match está vacío y descartaremos el resto. De esta manera, eliminaremos los duplicados y solo tendremos en nuestros resultados todos los campos distintos de ambas colecciones/tablas. (Puede haber notado en la salida del paso 2 que hay duplicados, por ejemplo: hay dos registros de Nikita)
Finalmente, eliminaremos el campo Notas vacío del resultado de la agregación, ya que es un campo vacío y no tiene sentido mostrarlo. Su objetivo era eliminar los duplicados.
Código:
db.J2.aggregate([{$redact:{$cond:[{$eq:["$Notas",[]]},"$KEEP","$PRUNE"]}},
{$unset:"Notas"}])

[Ampliar salida]
Así que finalmente tenemos nuestra salida deseada. Tenemos todos los registros que coinciden en ambas tablas (colecciones), así como otros registros presentes en una de las tablas (colecciones). (Deepak en Notas y número de matrícula 3D5RE en Rango).
Conclusión
Así que hemos logrado diferentes tipos de uniones a partir de una unión izquierda en MongoDB. Para resumir, solo hay una sintaxis directa disponible en MongoDB para realizar uniones izquierdas. Otros tipos de uniones deben derivarse aplicando diferentes tipos de operaciones y técnicas a la unión izquierda. Por ejemplo, eliminar colecciones con un campo as vacío en el caso de una unión interna, etc.
Al derivar estas uniones, nos dimos cuenta de lo siguiente:
- Es necesario tener un buen conocimiento de las consultas de agregación.
- Es necesario observar cuidadosamente los resultados intermedios para decidir el siguiente paso.
- Puede haber otras formas (incluso mejores) de derivar las uniones.
Si conoces mejores formas, puedes compartirlas en los comentarios.
Puntos clave
- Solo la operación de unión izquierda tiene una sintaxis directa en MongoDB.
- Deriva la unión derecha alterando la posición de las colecciones en la sintaxis.
- Deriva la unión interna realizando primero una unión izquierda y luego eliminando el campo as vacío.
- Las uniones externas se pueden realizar mediante una serie de operaciones simples y astutas.
Preguntas frecuentes
Referencias
- Documentación de MongoDB sobre Lookup
- Documentación oficial de MongoDB sobre $redact
- MongoDB Inner Join 101: Sintaxis y ejemplo simplificado por Samuel Salimon
El contenido mostrado en este artículo no es propiedad de Analytics Vidhya y se utiliza a discreción del autor.