Como usar $lookup no MongoDB

MongoDB é um banco de dados NoSQL popular que armazena dados em coleções. As coleções do MongoDB são compostas por um ou mais documentos que contêm os dados reais no formato JSON. Documentos são comparáveis ​​a linhas em bancos de dados SQL relacionais tradicionais, enquanto coleções são análogas a tabelas.

Uma funcionalidade chave em bancos de dados é a capacidade de consultar os dados armazenados no banco de dados. A consulta de dados permite a recuperação de informações específicas, análise de dados, relatórios de dados e também integração de dados.

Para poder consultar um banco de dados de forma eficaz, é crucial poder combinar dados de várias tabelas, no caso de bancos de dados SQL ou várias coleções em bancos de dados NOSQL, em um único conjunto de resultados.

No MongoDB $lookup usuários para combinar informações de duas coleções ao consultar. Ele executa o equivalente a uma junção externa esquerda em um banco de dados SQL.

Uso e objetivo de $lookup

Uma função importante dos bancos de dados é o processamento de dados para obter informações significativas dos dados brutos.

Por exemplo, se você administra um restaurante, pode querer analisar os dados de seu restaurante para descobrir quanto ganha por dia, quais alimentos são procurados nos fins de semana ou até mesmo descobrir quantas xícaras de café você vende em um restaurante. cada hora do dia.

Para tais necessidades, simples consultas ao banco de dados não serão suficientes. Você precisa realizar consultas avançadas sobre os dados armazenados. Para atender a essas necessidades, o MongoDB possui um recurso chamado pipeline de agregação.

Um pipeline de agregação é um sistema composto por operações compostas chamadas estágios, que são usadas para processar dados para produzir um resultado agregado final. Exemplos de estágios no pipeline de agregação incluem $sort, $match, $group, $merge, $count e $lookup, entre outros.

Esses estágios podem ser aplicados em qualquer ordem em um pipeline de agregação. Em cada estágio de um pipeline de agregação, diferentes operações são executadas nos dados que passam pelo pipeline de agregação.

$lookup é, portanto, um estágio no pipeline de agregação do MongoDB. $Lookup é usado para executar uma junção externa esquerda entre duas coleções em um banco de dados MongoDB. Uma junção externa esquerda combina todos os documentos ou entradas à esquerda com documentos ou entradas correspondentes à direita.

Por exemplo, considere as duas coleções abaixo, que foram representadas em formato tabular para facilitar o entendimento:

  5 melhores lugares para encontrar talentos on-line - contrate talentos remotos

pedidos_coleção:

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

customer_collection:

customer_numcustomer_namecustomer_emailcustomer_phone100John [email protected] [email protected]

Se realizarmos uma junção externa esquerda nas coleções acima usando o campo customer_id, que aparece na order_collection, com order_collection sendo a coleção esquerda e a customers_collection sendo a coleção direita, o resultado conterá todos os documentos na coleção Orders e documentos na coleção Customers que tem um customer_num que corresponde a um customer_id de qualquer um dos registros na coleção Orders.

O resultado final da operação de junção externa esquerda nas coleções orders e customers se parece com isso quando representado em formato tabular:

Observe que, para o cliente com customer_id 101 na coleção Orders, que não tinha nenhum valor customer_num correspondente na coleção Customers, os valores correspondentes ausentes da tabela customer foram preenchidos com nulo.

$lookup realiza comparações de igualdade estrita entre os campos e recupera todo o documento correspondente, e não apenas os campos correspondentes.

Sintaxe $lookup

A sintaxe para $lookup é a seguinte:

{
   $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 tem quatro parâmetros:

  • from – representa a coleção da qual queremos pesquisar documentos. Em nosso exemplo anterior usando orders_collection e customers_collection, colocaríamos customers_collection como o da coleção.
  • localField – este é um campo na coleção principal ou de trabalho que usamos para comparar com campos em nossa coleção from (customers_collection em nosso caso). No exemplo acima, o localField seria customer_id que é encontrado em orders_collection.
  • ForeignField – este é o campo com o qual queremos comparar na coleção que especificamos. Em nosso exemplo, isso seria customer_num encontrado em customer_collection que usamos como nosso valor em from
  • as – este é um novo nome de campo que especificamos para representar o campo que aparecerá em nosso documento, que contém documentos resultantes de correspondências entre localField e estrangeiraField. Todas essas correspondências são colocadas em uma matriz neste campo. Se não houver correspondências, este campo conterá uma matriz vazia.

De nossas duas coleções anteriores, usaríamos o código a seguir para realizar uma operação $lookup nas duas coleções com orders_collection como nossa coleção principal ou de trabalho.

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

Observe que o campo as pode ser qualquer valor de string. No entanto, se você atribuir um nome que já existe no documento de trabalho, esse campo será substituído.

Unindo dados de várias coleções

MongoDB $lookup é um estágio útil em um pipeline de agregação no MongoDB. Embora não seja um requisito que um pipeline de agregação no MongoDB tenha um estágio $lookup, o estágio é crucial ao executar consultas complexas que exigem a junção de dados em várias coleções.

O estágio $lookup executa uma junção externa à esquerda em duas coleções que resulta na criação de um novo campo ou na substituição dos valores de um campo existente por uma matriz contendo documentos de outra coleção.

  erro: redefinição de ap_hack_apr_allocator_create

Esses documentos são selecionados com base em se eles têm valores que correspondem aos valores do campo com o qual estão sendo comparados. O resultado final é um campo contendo uma matriz de documentos caso sejam encontradas correspondências ou uma matriz vazia caso nenhuma correspondência seja encontrada.

Considere as coleções do funcionário e do projeto mostradas abaixo.

Podemos usar o seguinte código para unir as duas coleções:

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

O resultado desta operação é uma combinação das duas coleções. O resultado são os projetos e todos os funcionários designados para cada projeto. Os funcionários são representados em uma matriz.

Estágios de pipeline que podem ser usados ​​em conjunto com $lookup

Conforme mencionado anteriormente, $lookup é um estágio em um pipeline de agregação do MongoDB e pode ser usado junto com outros estágios do pipeline de agregação. Para mostrar como esses estágios podem ser usados ​​junto com $lookup, usaremos as duas coleções a seguir para fins de ilustração.

No MongoDB, eles são armazenados no formato JSON. É assim que as coleções acima se parecem no MongoDB.

Alguns exemplos de estágios de pipeline de agregação que podem ser usados ​​junto com $lookup incluem:

$correspondência

$match é um estágio de pipeline de agregação usado para filtrar o fluxo de documentos para permitir que apenas os documentos que atendem à condição fornecida prossigam para o próximo estágio no pipeline de agregação. Esse estágio é melhor usado no início do pipeline para remover documentos que não serão necessários e, assim, otimizar o pipeline de agregação.

Usando as duas coleções anteriores, você pode combinar $match e $lookup assim:

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

$match é usado para filtrar usuários dos EUA. O resultado de $match é combinado com $lookup para obter os detalhes do pedido de usuários dos EUA. O resultado da operação acima é mostrado abaixo:

$projeto

$project é um estágio usado para remodelar documentos especificando quais campos incluir, excluir ou adicionar aos documentos. Por exemplo, caso você esteja processando documentos com dez campos cada, mas apenas quatro campos nos documentos contenham dados necessários para o processamento de dados, você pode usar $project para filtrar os campos desnecessários.

Isso permite evitar o envio de dados desnecessários para o próximo estágio do pipeline de agregação.

Podemos combinar $lookup e $project assim:

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

O acima combina as coleções de usuários e pedidos usando $lookup, então $project é usado para exibir apenas o nome de cada usuário e o valor gasto por cada usuário. $project também é usado para remover o campo _id dos resultados. O resultado da operação acima é mostrado abaixo:

  Como fazer com que os aplicativos do iPhone sempre solicitem acesso ao local

$descontrair

$unwind é um estágio de agregação usado para desconstruir ou desenrolar um campo de array criando novos documentos para cada elemento no array. Isso é útil caso você queira executar alguma agregação nos valores do campo da matriz.

Por exemplo, no exemplo abaixo, caso você queira fazer uma agregação no campo hobbies, você não pode fazer isso porque é um array. No entanto, você pode usar unwind usando $unwind e, em seguida, executar agregações nos documentos resultantes.

Usando as coleções users e orders, podemos usar $lookup e $unwind juntos da seguinte forma:

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

No código acima, $lookup retorna um campo de array chamado orders. $unwind é então usado para desenrolar o campo da matriz. O resultado dessa operação é mostrado a seguir: Observe que Alice aparece duas vezes porque ela tinha dois pedidos.

Exemplos de casos de uso de $lookup

Ao executar o processamento de dados, $lookup é uma ferramenta útil. Por exemplo, você pode ter duas coleções que deseja unir com base nos campos das coleções que possuem dados semelhantes. Um simples estágio $lookup pode ser usado para fazer isso e adicionar um novo campo nas coleções primárias, que contêm documentos obtidos de outra coleção.

Considera as coleções de usuários e pedidos mostradas abaixo:

As duas coleções podem ser combinadas usando $lookup para obter o resultado mostrado abaixo:

$lookup também pode ser usado para executar junções mais complexas. $lookup não se limita apenas a executar a união em duas coleções. Você pode implementar vários estágios $lookup para executar junções em mais de duas coleções. Considere as três coleções mostradas abaixo:

Podemos usar o código abaixo para realizar uma junção mais complexa entre as três coleções para obter todos os pedidos que foram feitos e também detalhes dos produtos que foram pedidos.

O código abaixo nos permite fazer exatamente isso:

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" }
      }
   }
])

O resultado da operação acima é mostrado abaixo:

Conclusão

Ao executar o processamento de dados envolvendo várias coleções, $lookup pode ser útil, pois permite que você junte dados e tire conclusões com base nos dados armazenados em várias coleções. O processamento de dados raramente depende de apenas uma coleta.

Para tirar conclusões significativas dos dados, juntar dados em várias coleções é uma etapa fundamental. Portanto, considere utilizar o estágio $lookup em seu pipeline de agregação do MongoDB para permitir que você processe melhor seus dados e obtenha insights significativos de dados brutos armazenados em coleções.

Você também pode explorar alguns comandos e consultas do MongoDB.