Definição
$lookup
Alterado na versão 8.0.
Executa uma junção externa esquerda em uma coleção no mesmo banco de dados para filtrar documentos da coleção estrangeira 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 estrangeira. 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
A sintaxe de estágio $lookup
:
{ $lookup: { from: <collection to join>, localField: <field from the input documents>, foreignField: <field from the documents of the "from" collection>, let: { <var_1>: <expression>, …, <var_n>: <expression> }, pipeline: [ <pipeline to run> ], as: <output array field> } }
O $lookup
aceita um documento com estes campos:
Campo | necessidade | Descrição |
---|---|---|
Obrigatório | Especifica a coleção estrangeira no mesmo banco de dados para ingressar na coleção local. É possível, em alguns casos extremos, substituir A partir do MongoDB 5.1, a coleção | |
Opcional se | Especifica o campo da entrada de documentos para o | |
Opcional se | Especifica o Se um documento externo não contiver um | |
Opcional | Especifica variáveis a serem usadas nos estágios do pipeline. Use as expressões variáveis para acessar os campos dos documentos da coleção local que são inseridos no Para fazer referência a variáveis em estágios do pipeline, use a As variáveis let podem ser acessadas pelos estágios no pipeline, incluindo os estágios adicionais
| |
Opcional se | Especifica o O O Para fazer referência a variáveis em estágios do pipeline, use a As variáveis let podem ser acessadas pelos estágios no pipeline, incluindo os estágios adicionais
| |
Obrigatório | 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 |
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 e um campo dos documentos da coleção estrangeira, a etapa $lookup
tem a seguinte sintaxe:
{ $lookup: { from: <collection to join>, localField: <field from the input documents>, foreignField: <field from the documents of the "from" collection>, pipeline: [ <pipeline to run> ], as: <output array field> } }
Observação
Neste exemplo, pipeline
é opcional e executado após o estágio de igualdade local e externa.
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 subqueries em uma coleção estrangeira
MongoDB suporta:
Executando um pipeline em uma coleção estrangeira.
Várias condições de junções.
Subconsultas correlacionadas e não correlacionadas.
No MongoDB, uma subquery não correlacionada significa que todo documento de entrada retornará o mesmo resultado. Uma subquery correlacionada é um pipeline em um estágio$lookup
que usa os campos da collection local ou input
para retornar resultados correlacionados a cada documento recebido.
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: <foreign collection>, let: { <var_1>: <expression>, …, <var_n>: <expression> }, pipeline: [ <pipeline to run on foreign collection> ], as: <output array field> } }
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 subquery correlacionada. As subqueries correlacionadas fazem referência a campos de documentos de uma coleção estrangeira 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> } }
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
Coleções criptografadas
A partir do MongoDB 8.1, você pode fazer referência a várias coleções criptografadas em um estágio$lookup
. No entanto, $lookup
não suporta:
Usando um campo criptografado como campo de junção no
localField
ouforeignField
.Observação
Para drivers que usam a criptografia em nível de campo do lado do cliente, você pode usar um campo criptografado como um campo de junção somente se estiver executando uma operação de autoassociação.
Usando qualquer campo em uma array criptografada. Uma array é considerada criptografada se contiver elementos criptografados.
Por exemplo, você não pode usar nenhum campo dentro do resultante as array da
$lookup
operação, a menos que esteja usando a Criptografia de Nível de Campo do Lado do Cliente e$unwind
oas
campo .
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 estrangeira, 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 foreign collection> ], // Cannot include $out or $merge as: <output array field> } }
Suporte de pesquisa do MongoDB
A partir do MongoDB 6.0, você pode especificar o estágio MongoDB Search $search
ou $searchMeta
no $lookup
pipeline para pesquisar collections no Atlas cluster. O $search
ou o $searchMeta
deve ser o primeiro estágio dentro do pipeline $lookup
.
Por exemplo, ao realizar Condições de junção e subqueries em uma coleção estrangeira ou executar Subqueries correlacionadas usando sintaxe concisa, você pode especificar $search
ou $searchMeta
dentro do pipeline, conforme mostrado abaixo:
Para ver um exemplo de $lookup
com $search
, veja o tutorial do MongoDB Search Executar uma query do MongoDB Search $search usando $lookup.
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 estrangeira. Para ver um exemplo desse tipo de operação, consulte Condições de união e subqueries em uma coleção estrangeira.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", foreign: new Date("2016-05-01"), status: "A" }, { _id: 2, name: "giraffe", foreign: new Date("2017-05-01"), status: "D" }, { _id: 3, name: "giraffe1", foreign: new Date("2017-10-01"), status: "A" }, { _id: 4, name: "panda", foreign: new Date("2018-10-11"), status: "A" }, { _id: 5, name: "pandabear", foreign: new Date("2018-12-01"), status: "A" }, { _id: 6, name: "giraffe2", foreign: 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", foreign: ISODate("2016-05-01T00:00:00Z"), status: "A" }, { _id: 5, name: "pandabear", foreign: ISODate("2018-12-01T00:00:00Z"), status: "A" }, { _id: 6, name: "giraffe2", foreign: 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", foreign: ISODate("2016-05-01T00:00:00Z"), status: "A" }, { _id: 3, name: "giraffe1", foreign: 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 externos 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 estrangeira 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 estrangeira. Isso permite uma subquery 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", localField : "item", foreignField : "stock_item", let : { order_qty: "$ordered" }, pipeline : [ { $match : { $expr : { $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 estrangeira, o que permite subqueries não correlacionadas. Uma subquery não correlacionada não faz referência aos campos do documento local.
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 exibe o array matches
e inclui todos os campos estrangeiros 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" ] } ] }
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
.
Os exemplos de C# nesta página utilizam o banco de dados sample_mflix
a partir dos conjuntos de dados de amostra do Atlas. Para saber como criar um cluster MongoDB Atlas gratuito e carregar os conjuntos de dados de exemplo, consulte Introdução na documentação do driver MongoDB .NET/C#.
A seguinte classe Movie
modela os documentos na collection sample_mflix.movies
:
public class Movie { public ObjectId Id { get; set; } public int Runtime { get; set; } public string Title { get; set; } public string Rated { get; set; } public List<string> Genres { get; set; } public string Plot { get; set; } public ImdbData Imdb { get; set; } public int Year { get; set; } public int Index { get; set; } public string[] Comments { get; set; } [ ] public DateTime LastUpdated { get; set; } }
Observação
ConventionPack para Pascal Case
As classes C# nesta página usam Pascal case para seus nomes de propriedade, mas os nomes de campo na coleção MongoDB usam Camel case. Para considerar essa diferença, você pode usar o seguinte código para registrar um ConventionPack
quando o aplicativo iniciar:
var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() }; ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);
A seguinte classe Comment
modela os documentos na collection sample_mflix.comments
:
public class Comment { public Guid Id { get; set; } [ ] public Guid MovieId { get; set; } public string Text { get; set; } }
Para usar o driver MongoDB .NET/C# para adicionar um estágio $lookup
a um pipeline de agregação, chame o método Lookup() em um objeto PipelineDefinition
.
O exemplo abaixo cria um estágio de pipeline que executa uma junção externa esquerda entre as collections movies
e comments
. O código une o campo Id
de cada documento Movie
ao campo MovieId
nos documentos Comment
. Os comentários de cada filme são armazenados em um campo chamado Comments
em cada documento Movie
.
var commentCollection = client .GetDatabase("aggregation_examples") .GetCollection<Comment>("comments"); var pipeline = new EmptyPipelineDefinition<Movie>() .Lookup<Movie, Movie, Comment, Movie>( foreignCollection: commentCollection, localField: m => m.Id, foreignField: c => c.MovieId, @as: m => m.Comments);
Os exemplos do Node.js nesta página utilizam o banco de dados do sample_mflix
a partir dos conjuntos de dados de amostra do Atlas. Para saber como criar um cluster gratuito do MongoDB Atlas e carregar os conjuntos de dados de exemplo, consulte Introdução na documentação do driver do MongoDB Node.js
Para usar o driver Node.js do MongoDB para adicionar um estágio $lookup
a um pipeline de agregação , use o operador $lookup
em um objeto de pipeline.
O exemplo a seguir cria um estágio de pipeline que executa uma junção externa esquerda entre as coleções movies
e comments
. O código conecta o campo _id
de cada documento movie
ao campo movie_id
nos documentos comment
. O campo comments
armazena os comentários de cada filme em cada documento movie
. O exemplo em seguida executa o pipeline de agregação:
const pipeline = [ { $lookup: { from: "comments", localField: "_id", foreignField: "movie_id", as: "comments" } } ]; const cursor = collection.aggregate(pipeline); return cursor;