Cómo usar $búsqueda en MongoDB

MongoDB es una base de datos NoSQL popular que almacena datos en colecciones. Las colecciones de MongoDB se componen de uno o más documentos que contienen los datos reales en formato JSON. Los documentos son comparables a las filas en las bases de datos SQL relacionales tradicionales, mientras que las colecciones son análogas a las tablas.

Una funcionalidad clave en las bases de datos es la capacidad de consultar los datos almacenados en la base de datos. La consulta de datos permite la recuperación de información específica, análisis de datos, informes de datos y también integración de datos.

Para poder consultar una base de datos de manera efectiva, es fundamental poder combinar datos de varias tablas, en el caso de bases de datos SQL o varias colecciones en bases de datos NOSQL, en un único conjunto de resultados.

En MongoDB $búsqueda de usuarios para combinar información de dos colecciones al realizar consultas. Realiza el equivalente a una combinación externa izquierda en una base de datos SQL.

Uso y objetivo de $lookup

Una función importante de las bases de datos es el procesamiento de datos para obtener información significativa de los datos sin procesar.

Por ejemplo, si tiene un restaurante, es posible que desee analizar los datos de su restaurante para averiguar cuánto gana todos los días, qué alimentos están en demanda los fines de semana o incluso averiguar a cuántas tazas de café vende. cada hora del día.

Para tales necesidades, las consultas simples a la base de datos no serán suficientes. Necesita realizar consultas avanzadas sobre los datos que tiene almacenados. Para abordar tales necesidades, MongoDB tiene una característica llamada tubería de agregación.

Una canalización de agregación es un sistema compuesto por operaciones componibles denominadas etapas, que se utilizan para procesar datos para producir un resultado agregado final. Los ejemplos de etapas en la canalización de agregación incluyen $sort, $match, $group, $merge, $count y $lookup, entre otros.

Estas etapas se pueden aplicar en cualquier orden en una canalización de agregación. En cada etapa de una canalización de agregación, se realizan diferentes operaciones en los datos que pasan a través de la canalización de agregación.

$lookup es, por lo tanto, una etapa en la canalización de agregación de MongoDB. $Lookup se usa para realizar una combinación externa izquierda entre dos colecciones en una base de datos MongoDB. Una combinación externa izquierda combina todos los documentos o entradas de la izquierda con los documentos o entradas coincidentes de la derecha.

Por ejemplo, considere las dos colecciones a continuación, que se han representado en formato tabular para facilitar la comprensión:

pedidos_colección:

order_idcustomer_idorder_datetotal_amount11002022-05-0150.0021012022-05-0275.0031022022-05-03100.00

colección_clientes:

numero_clientenombre_clientecustomer_emailcustomer_phone100John [email protected] [email protected]

Si realizamos una unión externa izquierda en las colecciones anteriores usando el campo id_cliente, que aparece en la colección_pedido, siendo colección_pedido la colección izquierda y colección_clientes la colección derecha, el resultado contendrá todos los documentos en la colección de pedidos y documentos en la Colección de Clientes que tienen un número_cliente que coincide con un id_cliente de cualquiera de los registros en la Colección de Pedidos.

El resultado final de la operación de combinación externa izquierda en las colecciones de pedidos y clientes se ve así cuando se representa en formato tabular:

Tenga en cuenta que para el cliente con id_cliente 101 en la Colección de pedidos, que no tenía un valor de número_cliente coincidente en la Colección de clientes, los valores correspondientes faltantes de la tabla de clientes se han rellenado con nulo.

$lookup realiza una comparación estricta de igualdad entre campos y recupera todo el documento que coincidió, y no solo los campos que coincidieron.

Sintaxis de $búsqueda

La sintaxis de $búsqueda es la siguiente:

{
   $lookup:
     {
       from: <collection to join>,
       localField: <field from the input documents>,
       foreignField: <field from the documents of the "from" collection>,
       as: <output array field>
     }
}

$lookup tiene cuatro parámetros:

  • from – representa la colección de la que queremos buscar documentos. En nuestro ejemplo anterior usando orders_collection y clients_collection, pondríamos clients_collection como from the collection.
  • localField: este es un campo en la colección principal o de trabajo que usamos para comparar con los campos en nuestra colección from (customers_collection en nuestro caso). En el ejemplo anterior, localField sería customer_id, que se encuentra en orders_collection.
  • ForeignField: este es el campo con el que queremos comparar en la colección que especificamos desde. En nuestro ejemplo, este sería el número_cliente que se encuentra en la colección_cliente que usamos como nuestro valor en from
  • as: este es un nuevo nombre de campo que especificamos para representar el campo que aparecerá en nuestro documento, que contiene documentos resultantes de coincidencias entre el campo local y el campo extranjero. Todas estas coincidencias se colocan en una matriz en este campo. Si no hay coincidencias, este campo contendrá una matriz vacía.

De nuestras dos colecciones anteriores, usaríamos el siguiente código para realizar una operación de $búsqueda en las dos colecciones con orders_collection como nuestra colección principal o de trabajo.

{
    $lookup: {
      from: "customers_collection",
      localField: "customer_id",
      foreignField: "customer_num",
      as: "customer_info"
 }

Tenga en cuenta que el campo como puede ser cualquier valor de cadena. Sin embargo, si le da un nombre que ya existe en el documento de trabajo, ese campo se sobrescribirá.

Unión de datos de varias colecciones

MongoDB $lookup es una etapa útil en una canalización de agregación en MongoDB. Aunque no es un requisito que una canalización de agregación en MongoDB deba tener una etapa $lookup, la etapa es crucial cuando se realizan consultas complejas que requieren unir datos en varias colecciones.

La etapa $lookup realiza una combinación externa izquierda en dos colecciones, lo que da como resultado la creación de un nuevo campo o la sobrescritura de los valores de un campo existente con una matriz que contiene documentos de otra colección.

Estos documentos se seleccionan en función de si tienen valores que coincidan con los valores del campo con el que se comparan. El resultado final es un campo que contiene una matriz de documentos en caso de que se encuentren coincidencias o una matriz vacía en caso de que no se encuentren coincidencias.

Considere las colecciones de empleados y proyectos que se muestran a continuación.

Podemos usar el siguiente código para unir las dos colecciones:

db.projects.aggregate([
   {
      $lookup: {
         from: "employees",
         localField: "employees",
         foreignField: "_id",
         as: "assigned_employees"
      }
   }
])

El resultado de esta operación es una combinación de las dos colecciones. El resultado son los proyectos y todos los empleados asignados a cada proyecto. Los empleados se representan en una matriz.

Pipeline Stages que se pueden usar junto con $lookup

Como se mencionó anteriormente, $lookup es una etapa en una canalización de agregación de MongoDB y se puede usar junto con otras etapas de canalización de agregación. Para mostrar cómo se pueden usar estas etapas junto con $lookup, usaremos las siguientes dos colecciones con fines ilustrativos.

En MongoDB, se almacenan en formato JSON. Así es como se ven las colecciones anteriores en MongoDB.

Algunos ejemplos de etapas de canalización de agregación que se pueden usar junto con $lookup incluyen:

$coincidencia

$match es una etapa de canalización de agregación que se usa para filtrar el flujo de documentos para permitir que solo aquellos documentos que cumplan con la condición dada pasen a la siguiente etapa en la canalización de agregación. Esta etapa se utiliza mejor al principio de la canalización para eliminar documentos que no serán necesarios y, por lo tanto, optimizar la canalización de agregación.

Usando las dos colecciones anteriores, puede combinar $match y $lookup así:

db.users.aggregate([
   {
      $match: {
         country: "USA"
      }
   },
   {
      $lookup: {
         from: "orders",
         localField: "_id",
         foreignField: "user_id",
         as: "orders"
      }
   }
])

$match se usa para filtrar usuarios de EE. UU. El resultado de $match se combina luego con $lookup para obtener los detalles del pedido de los usuarios de EE. UU. El resultado de la operación anterior se muestra a continuación:

$proyecto

$project es una etapa utilizada para remodelar documentos especificando qué campos incluir, excluir o agregar a los documentos. Por ejemplo, en caso de que esté procesando documentos con diez campos cada uno, pero solo cuatro campos en los documentos contienen datos que necesita para su procesamiento de datos, puede usar $project para filtrar los campos que no necesita.

Esto le permite evitar el envío de datos innecesarios a la siguiente etapa de su canalización de agregación.

Podemos combinar $búsqueda y $proyecto así:

db.users.aggregate([
   {
      $lookup: {
         from: "orders",
         localField: "_id",
         foreignField: "user_id",
         as: "orders"
      }
   },
   {
      $project: {
         name: 1,
         _id: 0,
         total_spent: { $sum: "$orders.price" }
      }
   }
])

Lo anterior combina las colecciones de usuarios y pedidos usando $búsqueda, luego $proyecto se usa para mostrar solo el nombre de cada usuario y la cantidad gastada por cada usuario. $project también se usa para eliminar el campo _id de los resultados. El resultado de la operación anterior se muestra a continuación:

$relajarse

$unwind es una etapa de agregación utilizada para deconstruir o deshacer un campo de matriz creando nuevos documentos para cada elemento de la matriz. Esto es útil en caso de que desee ejecutar alguna agregación en los valores de campo de matriz.

Por ejemplo, en el siguiente ejemplo, en caso de que desee ejecutar la agregación en el campo de pasatiempos, no puede hacerlo porque es una matriz. Sin embargo, puede desenrollarlo usando $unwind y luego realizar agregaciones en los documentos resultantes.

Usando las colecciones de usuarios y pedidos, podemos usar $lookup y $unwind juntos así:

db.users.aggregate([
   {
      $lookup: {
         from: "orders",
         localField: "_id",
         foreignField: "user_id",
         as: "orders"
      }
   },
   {
      $unwind: "$orders"
   }
])

En el código anterior, $búsqueda devuelve un campo de matriz llamado pedidos. Luego se usa $unwind para desenredar el campo de la matriz. El resultado de esta operación se muestra a continuación: Observe que Alicia aparece dos veces porque tenía dos pedidos.

Ejemplos de casos de uso de $búsqueda

Al realizar el procesamiento de datos, $lookup es una herramienta útil. Por ejemplo, puede tener dos colecciones que desea unir en función de los campos de las colecciones que tienen datos similares. Se puede usar una etapa simple de $búsqueda para hacer esto y agregar un nuevo campo en las colecciones primarias, que contienen documentos obtenidos de otra colección.

Considera las colecciones de usuarios y pedidos que se muestran a continuación:

Las dos colecciones se pueden combinar usando $lookup para obtener el resultado que se muestra a continuación:

$lookup también se puede usar para realizar uniones más complejas. $lookup no solo se limita a realizar la unión en dos colecciones. Puede implementar varias etapas de $búsqueda para realizar uniones en más de dos colecciones. Considere las tres colecciones que se muestran a continuación:

Podemos usar el código a continuación para realizar una combinación más compleja en las tres colecciones para obtener todos los pedidos que se realizaron y también los detalles de los productos que se ordenaron.

El siguiente código nos permite hacer precisamente eso:

db.orders.aggregate([
   {
      $lookup: {
         from: "order_items",
         localField: "_id",
         foreignField: "order_id",
         as: "order_items"
      }
   },
   {
      $unwind: "$order_items"
   },
   {
      $lookup: {
         from: "products",
         localField: "order_items.product_id",
         foreignField: "_id",
         as: "product_details"
      }
   },
   {
      $group: {
         _id: "$_id",
         customer: { $first: "$customer" },
         total: { $sum: "$order_items.price" },
         products: { $push: "$product_details" }
      }
   }
])

El resultado de la operación anterior se muestra a continuación:

Conclusión

Al realizar el procesamiento de datos que involucra múltiples colecciones, $lookup puede ser útil ya que le permite unir datos y sacar conclusiones basadas en datos almacenados en múltiples colecciones. El procesamiento de datos rara vez se basa en una sola colección.

Para sacar conclusiones significativas de los datos, unir datos en múltiples colecciones es un paso clave. Por lo tanto, considere utilizar la etapa $lookup en su canal de agregación de MongoDB para permitirle procesar mejor sus datos y obtener información significativa de los datos sin procesar almacenados en las colecciones.

También puede explorar algunos comandos y consultas de MongoDB.