$lookup (agregação)
Nesta página
- Definição
- Compatibilidade
- Sintaxe
- Correspondência de igualdade com uma única condição de junção
- Condições de junção e subconsultas em uma coleção associada
- Subconsultas correlacionadas usando sintaxe concisa
- Comportamento
- Visualizações e agrupamento
- Restrições
- Suporte do Atlas Search
- Coleções fragmentadas
- Mecanismo de execução de consulta baseado em slot
- Considerações de desempenho
- Exemplos
- Realizar uma única junção de igualdade com
$lookup
- Use
$lookup
com uma array - Use
$lookup
com$mergeObjects
- Use várias condições de junção e uma subquery correlacionada
- Execute uma subconsulta não correlacionada
$lookup
- Execute uma subconsulta concisa correlacionada com
$lookup
- Namespaces em Subpipelines
Definição
$lookup
Alterado na versão 8.0.
Realiza uma união externa esquerda em uma coleção no mesmo banco de dados para filtrar documentos da coleção "unida" para processamento. O estágio
$lookup
adiciona um novo campo de matriz para cada documento de entrada. O novo campo de array contém os documentos correspondentes da coleção "unida". O estágio$lookup
passa esses documentos remodelados para o próximo estágio.A partir do MongoDB 5.1, é possível usar
$lookup
com coleções fragmentadas.Para combinar elementos de duas coleções diferentes, use o estágio de pipeline
$unionWith
.
Compatibilidade
Você pode utilizar o $lookup
para implantações hospedadas nos seguintes ambientes:
MongoDB Atlas: o serviço totalmente gerenciado para implantações do MongoDB na nuvem
MongoDB Enterprise: a versão autogerenciada e baseada em assinatura do MongoDB
MongoDB Community: uma versão com código disponível, de uso gratuito e autogerenciada do MongoDB
Sintaxe
O estágio $lookup
tem as variações de sintaxe mostradas nas seções a seguir.
Correspondência de igualdade com uma única condição de junção
Para realizar uma correspondência de igualdade entre um campo dos documentos de entrada com um campo dos documentos da coleção "associada", o estágio $lookup
possui esta sintaxe:
{ $lookup: { from: <collection to join>, localField: <field from the input documents>, foreignField: <field from the documents of the "from" collection>, as: <output array field> } }
O $lookup
pega um documento com estes campos:
Campo | Descrição |
---|---|
Especifica a coleção no mesmo banco de dados com a qual realizar a junção.
A partir do MongoDB 5.1, a coleção especificada no parâmetro | |
Especifica o campo da entrada de documentos para o | |
Especifica o nome do novo campo de array a ser adicionado aos documentos de entrada. O novo campo de array contém os documentos correspondentes da coleção |
A operação corresponde a esta declaração pseudo-SQL:
SELECT *, ( SELECT ARRAY_AGG(*) FROM <collection to join> WHERE <foreignField> = <collection.localField> ) AS <output array field> FROM collection;
Observação
As declarações SQL nesta página estão incluídas para comparação com a sintaxe do pipeline de agregação do MongoDB. As declarações SQL não são executáveis.
Para exemplos do MongoDB, consulte estas páginas:
Condições de junção e subconsultas em uma coleção associada
MongoDB suporta:
Execução de pipeline em uma coleção associada.
Várias condições de junções.
Subconsultas correlacionadas e não correlacionadas.
No MongoDB, uma sub-query correlacionada é um pipeline em um estágio $lookup
que faz referência a campos de documentos de uma coleção associada. Uma subquery não correlacionada não faz referência a campos associados.
Observação
A partir do MongoDB 5.0, para uma sub-query não correlacionada em um estágio de pipeline $lookup
que contém um estágio $sample
, o operador $sampleRate
ou o operador $rand
, a sub-query é sempre executada novamente se for repetida. Anteriormente, dependendo do tamanho da saída da sub-query, o resultado da sub-query era armazenado em cache ou a sub-query era executada novamente.
As subconsultas correlacionadas do MongoDB são comparáveis às subconsultas correlacionadas do SQL, onde a consulta interna faz referência a valores de consulta externa. Uma subconsulta SQL não correlacionada não faz referência a valores de consulta externa.
O MongoDB 5.0 também suporta subqueries correlacionadas concisas.
Para executar subconsultas correlacionadas e não correlacionadas com duas coleções e executar outras condições de junção além de uma única correspondência de igualdade, use esta sintaxe $lookup
:
{ $lookup: { from: <joined collection>, let: { <var_1>: <expression>, …, <var_n>: <expression> }, pipeline: [ <pipeline to run on joined collection> ], as: <output array field> } }
O estágio $lookup
aceita um documento com estes campos:
Campo | Descrição |
---|---|
Especifica a coleção no mesmo banco de dados para executar a operação de junção.
A partir do MongoDB 5.1, a coleção | |
Opcional. Especifica as variáveis a serem usadas nos estágios do pipeline. Use as expressões variáveis para acessar os campos dos documentos da collection unida que são inseridos no Para fazer referência a variáveis em estágios do pipeline, use a As variáveis de let podem ser acessadas pelos estágios no pipeline, incluindo os estágios adicionais aninhados
| |
Especifica o O O Para fazer referência a variáveis em estágios do pipeline, use a As variáveis de let podem ser acessadas pelos estágios no pipeline, incluindo os estágios adicionais aninhados
| |
Especifica o nome do novo campo de array a ser adicionado aos documentos associados. O novo campo de array contém os documentos correspondentes da coleção associada. Se o nome especificado já existir no documento associado, o campo existente será substituído. |
A operação corresponde a esta declaração pseudo-SQL:
SELECT *, <output array field> FROM collection WHERE <output array field> IN ( SELECT <documents as determined from the pipeline> FROM <collection to join> WHERE <pipeline> );
Veja os seguintes exemplos:
Subconsultas correlacionadas usando sintaxe concisa
Novidades na versão 5.0.
A partir do MongoDB 5.0, você pode usar uma sintaxe concisa para uma subconsulta correlacionada. As subconsultas correlacionadas fazem referência a campos de documentos de uma coleção "estrangeira" associada e da coleção "local" na qual o método aggregate()
foi executado.
A nova sintaxe concisa a seguir remove o requisito de uma correspondência de igualdade nos campos estrangeiros e local dentro de um operador $expr
:
{ $lookup: { from: <foreign collection>, localField: <field from local collection's documents>, foreignField: <field from foreign collection's documents>, let: { <var_1>: <expression>, …, <var_n>: <expression> }, pipeline: [ <pipeline to run> ], as: <output array field> } }
O $lookup
aceita um documento com estes campos:
Campo | Descrição |
---|---|
Especifica a coleção estrangeira no mesmo banco de dados para ingressar na coleção local.
A partir do MongoDB 5.1, a coleção | |
Especifica o Se um documento local não contiver um | |
Especifica o Se um documento externo não contiver um | |
Opcional. Especifica as variáveis a serem usadas nos estágios do pipeline. Use as expressões variáveis para acessar os campos do documento que são inseridos no Para fazer referência a variáveis em estágios do pipeline, use a As variáveis de let podem ser acessadas pelos estágios no pipeline, incluindo os estágios adicionais aninhados
| |
Especifica o O O Para fazer referência a variáveis em estágios do pipeline, use a As variáveis de let podem ser acessadas pelos estágios no pipeline, incluindo os estágios adicionais aninhados
| |
Especifica o nome do novo campo de array a ser adicionado aos documentos estrangeiros. O novo campo de array contém os documentos correspondentes da coleção estrangeira. Se o nome especificado já existir no documento estrangeiro, o campo existente será substituído. |
A operação corresponde a esta declaração pseudo-SQL:
SELECT *, <output array field> FROM localCollection WHERE <output array field> IN ( SELECT <documents as determined from the pipeline> FROM <foreignCollection> WHERE <foreignCollection.foreignField> = <localCollection.localField> AND <pipeline match condition> );
Veja este exemplo:
Comportamento
Visualizações e agrupamento
Se executar uma agregação que envolva múltiplas visualizações, como com $lookup
ou $graphLookup
, as visualizações deverão ter o mesmo agrupamento.
Restrições
Você não pode incluir os estágios $out
ou $merge
no estágio $lookup
. Ou seja, ao especificar um pipeline para a coleção associada, você não pode incluir nenhum dos estágios no campo pipeline
.
{ $lookup: { from: <collection to join>, let: { <var_1>: <expression>, …, <var_n>: <expression> }, pipeline: [ <pipeline to execute on the joined collection> ], // Cannot include $out or $merge as: <output array field> } }
Suporte do Atlas Search
A partir do MongoDB 6.0, você pode especificar o $search
do Atlas Search ou o estágio do $searchMeta
no pipeline de $lookup
para pesquisar coleções no cluster do Atlas. O estágio $search
ou $searchMeta
deve ser o primeiro dentro do pipeline $lookup
.
Por exemplo, ao realizar Condições de junção e subconsultas em uma coleção associada ou executar Subconsultas correlacionadas usando sintaxe concisa, você pode especificar $search
ou $searchMeta
dentro do pipeline, conforme mostrado abaixo:
[{ "$lookup": { "from": <joined collection>, localField: <field from the input documents>, foreignField: <field from the documents of the "from" collection>, "as": <output array field>, "pipeline": [{ "$search": { "<operator>": { <operator-specification> } }, ... }] } }]
[{ "$lookup": { "from": <joined collection>, localField: <field from the input documents>, foreignField: <field from the documents of the "from" collection>, "as": <output array field>, "pipeline": [{ "$searchMeta": { "<collector>": { <collector-specification> } }, ... }] } }]
Para ver um exemplo de $lookup
com $search
, consulte o tutorial Executar uma query $search do Atlas Search usando $lookup, do Atlas Search.
Coleções fragmentadas
A partir do MongoDB 5.1, você pode especificar coleções fragmentadas no parâmetro from
de $lookup
estágios.
A partir do MongoDB 8.0, você pode usar o estágio $lookup
em uma transação enquanto visa uma coleção fragmentada.
Mecanismo de execução de consulta baseado em slot
A partir da versão 6.0, o MongoDB pode usar o mecanismo de execução de query baseado em slots para executar $lookup
estágios se todos os estágios anteriores no pipeline também puderem ser executados pelo mecanismo de execução baseado em slots e nenhuma das seguintes condições for verdadeira:
A operação
$lookup
executa um pipeline em uma coleção unida. Para ver um exemplo desse tipo de operação, consulte Condições de união e subqueries em uma coleção.Os
localField
ouforeignField
de$lookup
especificam componentes numéricos. Por exemplo:{ localField: "restaurant.0.review" }
.O campo
from
de qualquer$lookup
no pipeline especifica uma visualização ou coleção fragmentada.
Para mais informações, consulte Otimização do$lookup
.
Considerações de desempenho
$lookup
o desempenho depende do tipo de operação executada. Consulte a tabela a seguir para considerações de desempenho para diferentes operações do $lookup
.
$lookup (operação) | Considerações de desempenho |
---|---|
| |
| |
|
Para obter estratégias gerais de desempenho, consulte Estratégias de indexação e Otimização de consulta.
Importante
O uso excessivo de $lookup
em uma consulta pode diminuir o desempenho. Para evitar vários estágios $lookup
, adote um modelo de dados embutido para melhorar o desempenho da consulta.
Exemplos
Realizar uma única junção de igualdade com $lookup
Crie uma coleção orders
com estes documentos:
db.orders.insertMany( [ { "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2 }, { "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1 }, { "_id" : 3 } ] )
Crie outra coleção inventory
com estes documentos:
db.inventory.insertMany( [ { "_id" : 1, "sku" : "almonds", "description": "product 1", "instock" : 120 }, { "_id" : 2, "sku" : "bread", "description": "product 2", "instock" : 80 }, { "_id" : 3, "sku" : "cashews", "description": "product 3", "instock" : 60 }, { "_id" : 4, "sku" : "pecans", "description": "product 4", "instock" : 70 }, { "_id" : 5, "sku": null, "description": "Incomplete" }, { "_id" : 6 } ] )
A operação de agregação a seguir na coleção orders
une os documentos de orders
com os documentos da coleção inventory
usando os campos item
da coleção orders
e o campo sku
da coleção inventory
:
db.orders.aggregate( [ { $lookup: { from: "inventory", localField: "item", foreignField: "sku", as: "inventory_docs" } } ] )
A operação retorna estes documentos:
{ "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2, "inventory_docs" : [ { "_id" : 1, "sku" : "almonds", "description" : "product 1", "instock" : 120 } ] } { "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1, "inventory_docs" : [ { "_id" : 4, "sku" : "pecans", "description" : "product 4", "instock" : 70 } ] } { "_id" : 3, "inventory_docs" : [ { "_id" : 5, "sku" : null, "description" : "Incomplete" }, { "_id" : 6 } ] }
A operação corresponde a esta declaração pseudo-SQL:
SELECT *, inventory_docs FROM orders WHERE inventory_docs IN ( SELECT * FROM inventory WHERE sku = orders.item );
Para obter mais informações, consulte Considerações sobre o desempenho da correspondência de igualdade.
Use $lookup
com uma array
Se localField
for uma array, você poderá fazer a correspondência dos elementos de array com um escalar foreignField
sem um estágio $unwind
.
Por exemplo, crie uma coleção de exemplo classes
com estes documentos:
db.classes.insertMany( [ { _id: 1, title: "Reading is ...", enrollmentlist: [ "giraffe2", "pandabear", "artie" ], days: ["M", "W", "F"] }, { _id: 2, title: "But Writing ...", enrollmentlist: [ "giraffe1", "artie" ], days: ["T", "F"] } ] )
Crie outra coleção members
com estes documentos:
db.members.insertMany( [ { _id: 1, name: "artie", joined: new Date("2016-05-01"), status: "A" }, { _id: 2, name: "giraffe", joined: new Date("2017-05-01"), status: "D" }, { _id: 3, name: "giraffe1", joined: new Date("2017-10-01"), status: "A" }, { _id: 4, name: "panda", joined: new Date("2018-10-11"), status: "A" }, { _id: 5, name: "pandabear", joined: new Date("2018-12-01"), status: "A" }, { _id: 6, name: "giraffe2", joined: new Date("2018-12-01"), status: "D" } ] )
A seguinte operação de agregação une documentos na coleção classes
com a coleção members
, correspondendo o campo enrollmentlist
ao campo name
:
db.classes.aggregate( [ { $lookup: { from: "members", localField: "enrollmentlist", foreignField: "name", as: "enrollee_info" } } ] )
A operação retorna o seguinte:
{ "_id" : 1, "title" : "Reading is ...", "enrollmentlist" : [ "giraffe2", "pandabear", "artie" ], "days" : [ "M", "W", "F" ], "enrollee_info" : [ { "_id" : 1, "name" : "artie", "joined" : ISODate("2016-05-01T00:00:00Z"), "status" : "A" }, { "_id" : 5, "name" : "pandabear", "joined" : ISODate("2018-12-01T00:00:00Z"), "status" : "A" }, { "_id" : 6, "name" : "giraffe2", "joined" : ISODate("2018-12-01T00:00:00Z"), "status" : "D" } ] } { "_id" : 2, "title" : "But Writing ...", "enrollmentlist" : [ "giraffe1", "artie" ], "days" : [ "T", "F" ], "enrollee_info" : [ { "_id" : 1, "name" : "artie", "joined" : ISODate("2016-05-01T00:00:00Z"), "status" : "A" }, { "_id" : 3, "name" : "giraffe1", "joined" : ISODate("2017-10-01T00:00:00Z"), "status" : "A" } ] }
Usar $lookup
com $mergeObjects
O operador $mergeObjects
combina vários documentos em um único documento.
Crie uma coleção orders
com estes documentos:
db.orders.insertMany( [ { "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2 }, { "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1 } ] )
Crie outra coleção items
com estes documentos:
db.items.insertMany( [ { "_id" : 1, "item" : "almonds", description: "almond clusters", "instock" : 120 }, { "_id" : 2, "item" : "bread", description: "raisin and nut bread", "instock" : 80 }, { "_id" : 3, "item" : "pecans", description: "candied pecans", "instock" : 60 } ] )
A operação a seguir usa primeiro o estágio $lookup
para unir as duas coleções pelos campos item
e, em seguida, usa $mergeObjects
no $replaceRoot
para mesclar os documentos unidos de items
e orders
:
db.orders.aggregate( [ { $lookup: { from: "items", localField: "item", // field in the orders collection foreignField: "item", // field in the items collection as: "fromItems" } }, { $replaceRoot: { newRoot: { $mergeObjects: [ { $arrayElemAt: [ "$fromItems", 0 ] }, "$$ROOT" ] } } }, { $project: { fromItems: 0 } } ] )
A operação retorna estes documentos:
{ _id: 1, item: 'almonds', description: 'almond clusters', instock: 120, price: 12, quantity: 2 }, { _id: 2, item: 'pecans', description: 'candied pecans', instock: 60, price: 20, quantity: 1 }
Use várias condições de junção e uma subquery correlacionada
Os pipelines podem ser executados em uma coleção associada e incluir diversas condições de junção. O operador $expr
permite condições de junção mais complexas, incluindo conjunções e correspondências de não igualdade.
Uma condição de junção pode fazer referência a um campo na coleção local na qual o método aggregate()
foi executado e fazer referência a um campo na coleção associada. Isso permite uma subconsulta correlacionada entre as duas coleções.
O MongoDB 5.0 é compatível com subconsultas correlacionadas concisas.
Crie uma coleção orders
com estes documentos:
db.orders.insertMany( [ { "_id" : 1, "item" : "almonds", "price" : 12, "ordered" : 2 }, { "_id" : 2, "item" : "pecans", "price" : 20, "ordered" : 1 }, { "_id" : 3, "item" : "cookies", "price" : 10, "ordered" : 60 } ] )
Crie outra coleção warehouses
com estes documentos:
db.warehouses.insertMany( [ { "_id" : 1, "stock_item" : "almonds", warehouse: "A", "instock" : 120 }, { "_id" : 2, "stock_item" : "pecans", warehouse: "A", "instock" : 80 }, { "_id" : 3, "stock_item" : "almonds", warehouse: "B", "instock" : 60 }, { "_id" : 4, "stock_item" : "cookies", warehouse: "B", "instock" : 40 }, { "_id" : 5, "stock_item" : "cookies", warehouse: "A", "instock" : 80 } ] )
O seguinte exemplo:
Usa uma subconsulta correlacionada com uma junção nos campos
orders.item
ewarehouse.stock_item
.Garante que a quantidade do item em estoque possa atender à quantidade solicitada.
db.orders.aggregate( [ { $lookup: { from: "warehouses", let: { order_item: "$item", order_qty: "$ordered" }, pipeline: [ { $match: { $expr: { $and: [ { $eq: [ "$stock_item", "$$order_item" ] }, { $gte: [ "$instock", "$$order_qty" ] } ] } } }, { $project: { stock_item: 0, _id: 0 } } ], as: "stockdata" } } ] )
A operação retorna estes documentos:
{ _id: 1, item: 'almonds', price: 12, ordered: 2, stockdata: [ { warehouse: 'A', instock: 120 }, { warehouse: 'B', instock: 60 } ] }, { _id: 2, item: 'pecans', price: 20, ordered: 1, stockdata: [ { warehouse: 'A', instock: 80 } ] }, { _id: 3, item: 'cookies', price: 10, ordered: 60, stockdata: [ { warehouse: 'A', instock: 80 } ] }
A operação corresponde a esta declaração pseudo-SQL:
SELECT *, stockdata FROM orders WHERE stockdata IN ( SELECT warehouse, instock FROM warehouses WHERE stock_item = orders.item AND instock >= orders.ordered );
Os operadores de comparação $eq
, $lt
, $lte
, $gt
e $gte
colocados em um operador $expr
podem utilizar um índice na coleção from
referenciada em um estágio $lookup
. Limitações:
Os índices só podem ser usados para comparações entre campos e constantes, portanto, o operando
let
deve ser resolvido para uma constante.Por exemplo, uma comparação entre
$a
e um valor constante pode usar um índice, mas uma comparação entre$a
e$b
não pode.Os índices não são usados para comparações onde o operando
let
resolve para um valor vazio ou ausente.Índices multichave não são usados.
Por exemplo, se o índice { stock_item: 1, instock: 1 }
existir na coleção warehouses
:
A correspondência de igualdade no campo
warehouses.stock_item
utiliza o índice.A parte da faixa da consulta no campo
warehouses.instock
também utiliza o campo indexado no índice composto.
Execute uma subconsulta não correlacionada $lookup
Um estágio $lookup
do pipeline de agregação pode executar um pipeline na coleção associada, o que permite subqueries não correlacionadas. Uma subquery não correlacionada não faz referência aos campos do documento associado.
Observação
A partir do MongoDB 5.0, para uma sub-query não correlacionada em um estágio de pipeline $lookup
que contém um estágio $sample
, o operador $sampleRate
ou o operador $rand
, a sub-query é sempre executada novamente se for repetida. Anteriormente, dependendo do tamanho da saída da sub-query, o resultado da sub-query era armazenado em cache ou a sub-query era executada novamente.
Crie uma coleção absences
com estes documentos:
db.absences.insertMany( [ { "_id" : 1, "student" : "Ann Aardvark", sickdays: [ new Date ("2018-05-01"),new Date ("2018-08-23") ] }, { "_id" : 2, "student" : "Zoe Zebra", sickdays: [ new Date ("2018-02-01"),new Date ("2018-05-23") ] }, ] )
Crie outra coleção holidays
com estes documentos:
db.holidays.insertMany( [ { "_id" : 1, year: 2018, name: "New Years", date: new Date("2018-01-01") }, { "_id" : 2, year: 2018, name: "Pi Day", date: new Date("2018-03-14") }, { "_id" : 3, year: 2018, name: "Ice Cream Day", date: new Date("2018-07-15") }, { "_id" : 4, year: 2017, name: "New Years", date: new Date("2017-01-01") }, { "_id" : 5, year: 2017, name: "Ice Cream Day", date: new Date("2017-07-16") } ] )
A operação a seguir une a coleção absences
às informações de feriados de 2018 da coleção holidays
:
db.absences.aggregate( [ { $lookup: { from: "holidays", pipeline: [ { $match: { year: 2018 } }, { $project: { _id: 0, date: { name: "$name", date: "$date" } } }, { $replaceRoot: { newRoot: "$date" } } ], as: "holidays" } } ] )
A operação retorna o seguinte:
{ _id: 1, student: 'Ann Aardvark', sickdays: [ ISODate("2018-05-01T00:00:00.000Z"), ISODate("2018-08-23T00:00:00.000Z") ], holidays: [ { name: 'New Years', date: ISODate("2018-01-01T00:00:00.000Z") }, { name: 'Pi Day', date: ISODate("2018-03-14T00:00:00.000Z") }, { name: 'Ice Cream Day', date: ISODate("2018-07-15T00:00:00.000Z") } ] }, { _id: 2, student: 'Zoe Zebra', sickdays: [ ISODate("2018-02-01T00:00:00.000Z"), ISODate("2018-05-23T00:00:00.000Z") ], holidays: [ { name: 'New Years', date: ISODate("2018-01-01T00:00:00.000Z") }, { name: 'Pi Day', date: ISODate("2018-03-14T00:00:00.000Z") }, { name: 'Ice Cream Day', date: ISODate("2018-07-15T00:00:00.000Z") } ] }
A operação corresponde a esta declaração pseudo-SQL:
SELECT *, holidays FROM absences WHERE holidays IN ( SELECT name, date FROM holidays WHERE year = 2018 );
Para obter mais informações, consulte Considerações sobre desempenho de subconsultas não correlacionadas.
Execute uma subconsulta concisa correlacionada com $lookup
Novidades na versão 5.0.
A partir do MongoDB 5.0, um estágio $lookup
do pipeline de agregação suporta uma sintaxe de sub-query correlacionada concisa que melhora as uniões entre coleções. A nova sintaxe concisa remove a exigência de uma correspondência de igualdade nos campos externo e local dentro de um operador $expr
em um estágio $match
.
Criar uma coleção restaurants
:
db.restaurants.insertMany( [ { _id: 1, name: "American Steak House", food: [ "filet", "sirloin" ], beverages: [ "beer", "wine" ] }, { _id: 2, name: "Honest John Pizza", food: [ "cheese pizza", "pepperoni pizza" ], beverages: [ "soda" ] } ] )
Crie outra coleção orders
com pedidos de comidas e bebidas opcionais:
db.orders.insertMany( [ { _id: 1, item: "filet", restaurant_name: "American Steak House" }, { _id: 2, item: "cheese pizza", restaurant_name: "Honest John Pizza", drink: "lemonade" }, { _id: 3, item: "cheese pizza", restaurant_name: "Honest John Pizza", drink: "soda" } ] )
O seguinte exemplo:
Associa as coleções
orders
erestaurants
combinando oorders.restaurant_name
localField com orestaurants.name
foreignField. A correspondência é executada antes depipeline
ser executado.Realiza uma correspondência de array
$in
entre os camposorders.drink
erestaurants.beverages
que são acessados usando$$orders_drink
e$beverages
, respectivamente.
db.orders.aggregate( [ { $lookup: { from: "restaurants", localField: "restaurant_name", foreignField: "name", let: { orders_drink: "$drink" }, pipeline: [ { $match: { $expr: { $in: [ "$$orders_drink", "$beverages" ] } } } ], as: "matches" } } ] )
Há uma correspondência para o valor soda
nos campos orders.drink
e restaurants.beverages
. Esta saída mostra a array matches
e contém todos os campos associados da coleção restaurants
para a correspondência:
{ "_id" : 1, "item" : "filet", "restaurant_name" : "American Steak House", "matches" : [ ] } { "_id" : 2, "item" : "cheese pizza", "restaurant_name" : "Honest John Pizza", "drink" : "lemonade", "matches" : [ ] } { "_id" : 3, "item" : "cheese pizza", "restaurant_name" : "Honest John Pizza", "drink" : "soda", "matches" : [ { "_id" : 2, "name" : "Honest John Pizza", "food" : [ "cheese pizza", "pepperoni pizza" ], "beverages" : [ "soda" ] } ] }
Antes da introdução de subqueries correlacionadas concisas, era necessário usar uma correspondência de igualdade $eq
entre o campo local e o campo unido no operador $expr
no estágio do pipeline
$lookup
conforme mostrado em Usar condições de união múltiplas e uma subquery correlacionada.
Este exemplo usa a sintaxe detalhada mais antiga das versões do MongoDB anteriores à 5.0 e retorna os mesmos resultados do exemplo conciso anterior:
db.orders.aggregate( [ { $lookup: { from: "restaurants", let: { orders_restaurant_name: "$restaurant_name", orders_drink: "$drink" }, pipeline: [ { $match: { $expr: { $and: [ { $eq: [ "$$orders_restaurant_name", "$name" ] }, { $in: [ "$$orders_drink", "$beverages" ] } ] } } } ], as: "matches" } } ] )
Os exemplos anteriores correspondem a esta declaração pseudo-SQL:
SELECT *, matches FROM orders WHERE matches IN ( SELECT * FROM restaurants WHERE restaurants.name = orders.restaurant_name AND restaurants.beverages = orders.drink );
Para mais informações, consulte Considerações sobre o desempenho de subconsultas correlacionadas.
Namespaces em Subpipelines
A partir do MongoDB 8.0, os namespaces em subpipelines dentro $lookup
e $unionWith
são validados para garantir o uso correto dos campos from
e coll
:
Por
$lookup
, omita o campofrom
se você usar um subpipeline com um estágio que não exija uma coleção especificada. Por exemplo, um estágio$documents
.Da mesma forma, para
$unionWith
, omita o campocoll
.
Comportamento inalterado:
Para um
$lookup
que começa com um estágio para uma coleção, por exemplo, um subpipeline$match
ou$collStats
, você deve incluir o campofrom
e especificar a coleção.Da mesma forma, para
$unionWith
, inclua o campocoll
e especifique a coleção.
O cenário a seguir mostra um exemplo.
Criar uma coleção cakeFlavors
:
db.cakeFlavors.insertMany( [ { _id: 1, flavor: "chocolate" }, { _id: 2, flavor: "strawberry" }, { _id: 3, flavor: "cherry" } ] )
A partir do MongoDB 8.0, o exemplo a seguir retorna um erro porque contém um campo from
inválido :
db.cakeFlavors.aggregate( [ { $lookup: { from: "cakeFlavors", pipeline: [ { $documents: [ {} ] } ], as: "test" } } ] )
Nas versões do MongoDB anteriores a 8.0, o exemplo anterior é executado.
Para obter um exemplo com um campo from
válido , consulte Executar uma única junção de igualdade com $lookup
.