Uso de uniones en bases de datos MongoDB NoSQL

Uso de $lookUp con NoSQL

Gracias a Julian Motz por ayudar amablemente a revisar este artículo.

Una de las mayores diferencias entre las bases de datos SQL y NoSQL es UNIRSE. En las bases de datos relacionales, la cláusula SQL JOIN permite combinar filas de dos o más tablas utilizando un campo común entre ellas. Por ejemplo, si tiene tablas de books y publishers, puede escribir comandos SQL como:

SELECT book.title, publisher.nameFROM bookLEFT JOIN book.publisher_id ON publisher.id;

En otras palabras, la tabla book tiene un campo publisher_id que hace referencia al campo id en la tabla publisher.

Esto es práctico, ya que un solo editor podría ofrecer miles de libros. Si alguna vez necesitamos actualizar los detalles de un editor, podemos cambiar un solo registro. La redundancia de datos se minimiza, ya que no necesitamos repetir la información del editor para cada libro. La técnica se conoce como normalización.

Las bases de datos SQL ofrecen una gama de características de normalización y restricción para garantizar que se mantengan las relaciones.

NoSQL = = ¿Sin UNIÓN?

No siempre

Las bases de datos orientadas a documentos, como MongoDB, están diseñadas para almacenar datos desnormalizados. Idealmente, no debería haber ninguna relación entre las colecciones. Si se requieren los mismos datos en dos o más documentos, debe repetirse.

Esto puede ser frustrante, ya que hay pocas situaciones en las que nunca se necesitan datos relacionales. Afortunadamente, MongoDB 3.2 introduce un nuevo operador $lookup que puede realizar una operación de UNIÓN EXTERNA IZQUIERDA en dos o más colecciones. Pero hay un problema

La agregación de MongoDB

$lookup solo se permite en operaciones de agregación. Piense en estos como una canalización de operadores que consultan, filtran y agrupan un resultado. La salida de un operador se utiliza como entrada para el siguiente.La agregación

es más difícil de entender que las consultas find más simples y generalmente se ejecutará más lentamente. Sin embargo, son potentes y una opción invaluable para operaciones de búsqueda complejas.La agregación

se explica mejor con un ejemplo. Supongamos que estamos creando una plataforma de redes sociales con una colección user. Almacena los detalles de cada usuario en documentos separados. Por ejemplo:

{ "_id": ObjectID("45b83bda421238c76f5c1969"), "name": "User One", "email: "[email protected]", "country": "UK", "dob": ISODate("1999-09-13T00:00:00.000Z")}

Podemos agregar tantos campos como sea necesario, pero todos los documentos MongoDB requieren un campo _id que tenga un valor único. _id es similar a una clave principal SQL, y se insertará automáticamente si es necesario.

Nuestra red social ahora requiere una colección post, que almacena numerosas actualizaciones detalladas de los usuarios. Los documentos almacenan el texto, la fecha, una calificación y una referencia al usuario que lo escribió en un campo user_id :

{ "_id": ObjectID("17c9812acff9ac0bba018cc1"), "user_id": ObjectID("45b83bda421238c76f5c1969"), "date: ISODate("2016-09-05T03:05:00.123Z"), "text": "My life story so far", "rating": "important"}

Ahora queremos mostrar las últimas veinte publicaciones con una calificación «importante» de todos los usuarios en orden cronológico inverso. Cada documento devuelto debe contener el texto, la hora de la publicación y el nombre y país del usuario asociado.

A la consulta agregada de MongoDB se le pasa una matriz de operadores de canalización que definen cada operación en orden. Primero, necesitamos extraer todos los documentos de la colección post que tengan la calificación correcta utilizando el filtro $match :

{ "$match": { "rating": "important" } }

Ahora debemos ordenar los elementos coincidentes en orden de fecha inverso utilizando el operador $sort :

{ "$sort": { "date": -1 } }

Dado que solo requerimos veinte publicaciones, podemos aplicar una etapa $limit, por lo que MongoDB solo necesita procesar los datos que queremos:

{ "$limit": 20 }

Ahora podemos unir datos de la colección user utilizando el nuevo operador $lookup. Requiere un objeto con cuatro parámetros:

  • localField: el campo de búsqueda en el documento de entrada
  • from: la colección a la que unirse
  • foreignField: el campo a buscar en la colección from
  • as: el nombre del campo de salida.

Nuestro operador es por lo tanto:

{ "$lookup": { "localField": "user_id", "from": "user", "foreignField": "_id", "as": "userinfo"} }

Esto creará un nuevo campo en nuestra salida llamado userinfo. Contiene una matriz en la que cada valor coincide con el documento user :

"userinfo": 

Tenemos una relación uno a uno entre post.user_id y user._id, ya que un post solo puede tener un autor. Por lo tanto, nuestro array userinfo solo contendrá un elemento. Podemos usar el operador $unwind para deconstruirlo en un sub-documento:

{ "$unwind": "$userinfo" }

La salida ahora se convertirá a un formato más práctico que puede tener operadores adicionales aplicados:

"userinfo": { "name": "User One", "email: "[email protected]", …}

Finalmente, podemos devolver el texto, la hora de la publicación, el nombre del usuario y el país utilizando una etapa $project en la canalización:

{ "$project": { "text": 1, "date": 1, "userinfo.name": 1, "userinfo.country": 1} }

Juntando Todo

Nuestra consulta agregada final coincide con los mensajes, ordena en orden, limita los últimos veinte elementos, une los datos de usuario, aplana la matriz de usuarios y devuelve solo los campos necesarios. El comando completo:

db.post.aggregate();

El resultado es una colección de hasta veinte documentos. Por ejemplo:

¡Genial! Finalmente puedo Cambiar a NoSQL!

MongoDB $lookup es útil y potente, pero incluso este ejemplo básico requiere una consulta agregada compleja. No es un sustituto de la cláusula de UNIÓN más potente que se ofrece en SQL. MongoDB tampoco ofrece restricciones; si se elimina un documento user, los documentos huérfanos post permanecerían.

Lo ideal es que el operador $lookup se requiera con poca frecuencia. Si lo necesita mucho, es posible que esté utilizando el almacén de datos incorrecto …

Si tiene datos relacionales, utilice una base de datos relacional (SQL).

Dicho esto, $lookup es una adición bienvenida a MongoDB 3.2. Puede superar algunos de los problemas más frustrantes al usar pequeñas cantidades de datos relacionales en una base de datos NoSQL.

You might also like

Deja una respuesta

Tu dirección de correo electrónico no será publicada.