Para agentes de IA: um índice de documentação está disponível em https://www.mongodb.com/pt-br/docs/llms.txt — as versões de markdown de todas as páginas estão disponíveis anexando .md a qualquer caminho de URL.
Menu Docs

$graphLookup (estágio de agregação )

$graphLookup

Alterado na versão 5.1.

Executa uma pesquisa recursiva em uma coleção, com opções para restringir a pesquisa por profundidade de recursão e filtro de consulta.

O processo de pesquisa $graphLookup está resumido abaixo:

  1. Documentos de entrada fluem para o estágio $graphLookup de uma operação de agregação.

  2. $graphLookup direciona a pesquisa para a coleção designada pelo parâmetro from (veja abaixo a lista completa de parâmetros de pesquisa).

  3. Para cada documento de entrada, a pesquisa começa com o valor designado por startWith.

  4. $graphLookup corresponde ao valor startWith contra o campo designado por connectToField em outros documentos na coleção from.

  5. Para cada documento correspondente, $graphLookup pega o valor de connectFromField e verifica cada documento na coleção from em busca de um valor correspondente a connectToField. Para cada correspondência, $graphLookup adiciona o documento correspondente na coleção from a um campo de array nomeado pelo parâmetro as .

    Essa etapa continua recursivamente até que não haja mais documentos correspondentes encontrados, ou até que a operação atinja uma profundidade de recursão especificada pelo parâmetro maxDepth. $graphLookup então acrescenta o campo de array ao documento de entrada. $graphLookup retorna os resultados após concluir sua pesquisa em todos os documentos de entrada.

$graphLookup tem a seguinte forma de protótipo:

{
$graphLookup: {
from: <collection>,
startWith: <expression>,
connectFromField: <string>,
connectToField: <string>,
as: <string>,
maxDepth: <number>,
depthField: <string>,
restrictSearchWithMatch: <document>
}
}

$graphLookup obtém um documento com os seguintes campos:

Campo
Descrição

from

Target collection for the $graphLookup operation to search, recursively matching the connectFromField to the connectToField. The from collection must be in the same database as any other collections used in the operation.

For sharding support, see Sharded Collections.

startWith

Expressão que especifica o valor do connectFromField com o qual iniciar a pesquisa recursiva. Se startWith avaliar para uma array, $graphLookup executa a pesquisa simultaneamente a partir de todos os elementos da array.

connectFromField

Field name whose value $graphLookup uses to recursively match against the connectToField of other documents in the collection. If the value is an array, each element is individually followed through the traversal process.

connectToField

Nome do campo em outros documentos para corresponder ao valor do campo especificado pelo parâmetro connectFromField.

as

Name of the array field added to each output document. Contains the documents traversed in the $graphLookup stage to reach the document.

Não é garantido que os documentos retornados no campo as estejam em qualquer ordem.

maxDepth

Opcional. Número integral não negativo, especificando a profundidade máxima da recursão.

depthField

Opcional. Nome do campo a ser adicionado a cada documento atravessado no caminho de pesquisa. O valor deste campo é a profundidade de recursão do documento, representado como um NumberLong. O valor da profundidade de recursão começa em zero, então a primeira pesquisa corresponde à profundidade zero.

restrictSearchWithMatch

Opcional. Um documento que especifica condições adicionais para a pesquisa recursiva. A sintaxe é idêntica à sintaxe do filtro de consulta.

Você não pode utilizar qualquer expressão de agregação neste filtro. Por exemplo, você não pode usar o seguinte documento para localizar documentos nos quais o valor lastName é diferente do valor lastName do documento de entrada:

{ lastName: { $ne: "$lastName" } }

Você não pode usar o documento neste contexto, porque "$lastName" atuará como uma string literalmente, e não como um caminho do campo.

A partir do MongoDB,5.1 você pode especificar collections fragmentadas no from parâmetro de $graphLookup estágios.

Você não pode usar a etapa $graphLookup dentro de uma transação enquanto segmenta uma coleção fragmentada.

Setting the maxDepth field to 0 is equivalent to a non-recursive $graphLookup search stage.

O estágio$graphLookupdeve ficar dentro do limite de memória 100 megabyte. Se o allowDiskUse: true for especificado para a operaçãoaggregate(), o estágio$graphLookupignorará a opção. Se houver outros estágios na operaçãoaggregate(), a opção allowDiskUse: true estará em vigor para esses outros estágios.

Consulte limites do pipeline de agregação para obter mais informações.

O estágio $graphLookup não retorna resultados ordenados. Para classificar seus resultados, use o $sortArray operador.

If performing an aggregation that involves multiple views, such as with $lookup or $graphLookup, the views must have the same collation.

Uma coleção chamada employees possui os seguintes documentos:

db.employees.insertMany( [
{ _id: 1, name: "Dev" },
{ _id: 2, name: "Eliot", reportsTo: "Dev" },
{ _id: 3, name: "Ron", reportsTo: "Eliot" },
{ _id: 4, name: "Andrew", reportsTo: "Eliot" },
{ _id: 5, name: "Asya", reportsTo: "Ron" },
{ _id: 6, name: "Dan", reportsTo: "Andrew" }
] )

The following $graphLookup operation recursively matches on the reportsTo and name fields in the employees collection, returning the reporting hierarchy for each person:

db.employees.aggregate( [
{
$graphLookup: {
from: "employees",
startWith: "$reportsTo",
connectFromField: "reportsTo",
connectToField: "name",
as: "reportingHierarchy"
}
}
] )
[
{ _id: 1, name: 'Dev', reportingHierarchy: [] },
{
_id: 2,
name: 'Eliot',
reportsTo: 'Dev',
reportingHierarchy: [ { _id: 1, name: 'Dev' } ]
},
{
_id: 3,
name: 'Ron',
reportsTo: 'Eliot',
reportingHierarchy: [
{ _id: 2, name: 'Eliot', reportsTo: 'Dev' },
{ _id: 1, name: 'Dev' }
]
},
{
_id: 4,
name: 'Andrew',
reportsTo: 'Eliot',
reportingHierarchy: [
{ _id: 2, name: 'Eliot', reportsTo: 'Dev' },
{ _id: 1, name: 'Dev' }
]
},
{
_id: 5,
name: 'Asya',
reportsTo: 'Ron',
reportingHierarchy: [
{ _id: 2, name: 'Eliot', reportsTo: 'Dev' },
{ _id: 3, name: 'Ron', reportsTo: 'Eliot' },
{ _id: 1, name: 'Dev' }
]
},
{
_id: 6,
name: 'Dan',
reportsTo: 'Andrew',
reportingHierarchy: [
{ _id: 2, name: 'Eliot', reportsTo: 'Dev' },
{ _id: 1, name: 'Dev' },
{ _id: 4, name: 'Andrew', reportsTo: 'Eliot' }
]
}
]

A tabela a seguir fornece um caminho transversal para o documento { "_id" : 5, "name" : "Asya", "reportsTo" : "Ron" }:

Valor inicial

O valor reportsTo do documento:

{ ... reportsTo: "Ron" }

Profundidade 0

{ _id: 3, name: "Ron", reportsTo: "Eliot" }

Profundidade 1

{ _id: 2, name: "Eliot", reportsTo: "Dev" }

Profundidade 2

{ _id: 1, name: "Dev" }

O resultado gera a hierarquia Asya -> Ron -> Eliot -> Dev.

Like $lookup, $graphLookup can access another collection in the same database.

Por exemplo, crie um banco de dados com duas coleções:

  • Uma coleção airports com os seguintes documentos:

    db.airports.insertMany( [
    { _id: 0, airport: "JFK", connects: [ "BOS", "ORD" ] },
    { _id: 1, airport: "BOS", connects: [ "JFK", "PWM" ] },
    { _id: 2, airport: "ORD", connects: [ "JFK" ] },
    { _id: 3, airport: "PWM", connects: [ "BOS", "LHR" ] },
    { _id: 4, airport: "LHR", connects: [ "PWM" ] }
    ] )
  • Uma coleção travelers com os seguintes documentos:

    db.travelers.insertMany( [
    { _id: 1, name: "Dev", nearestAirport: "JFK" },
    { _id: 2, name: "Eliot", nearestAirport: "JFK" },
    { _id: 3, name: "Jeff", nearestAirport: "BOS" }
    ] )

Para cada documento na coleção travelers, a seguinte operação de agregação procura o valor nearestAirport na coleção airports e recursivamente corresponde ao campo connects ao campo airport. A operação especifica uma profundidade máxima de recursão de 2.

db.travelers.aggregate( [
{
$graphLookup: {
from: "airports",
startWith: "$nearestAirport",
connectFromField: "connects",
connectToField: "airport",
maxDepth: 2,
depthField: "numConnections",
as: "destinations"
}
}
] )
[
{
_id: 1,
name: 'Dev',
nearestAirport: 'JFK',
destinations: [
{
_id: 0,
airport: 'JFK',
connects: [ 'BOS', 'ORD' ],
numConnections: Long('0')
},
{
_id: 1,
airport: 'BOS',
connects: [ 'JFK', 'PWM' ],
numConnections: Long('1')
},
{
_id: 3,
airport: 'PWM',
connects: [ 'BOS', 'LHR' ],
numConnections: Long('2')
},
{
_id: 2,
airport: 'ORD',
connects: [ 'JFK' ],
numConnections: Long('1')
}
]
},
{
_id: 2,
name: 'Eliot',
nearestAirport: 'JFK',
destinations: [
{
_id: 0,
airport: 'JFK',
connects: [ 'BOS', 'ORD' ],
numConnections: Long('0')
},
{
_id: 1,
airport: 'BOS',
connects: [ 'JFK', 'PWM' ],
numConnections: Long('1')
},
{
_id: 3,
airport: 'PWM',
connects: [ 'BOS', 'LHR' ],
numConnections: Long('2')
},
{
_id: 2,
airport: 'ORD',
connects: [ 'JFK' ],
numConnections: Long('1')
}
]
},
{
_id: 3,
name: 'Jeff',
nearestAirport: 'BOS',
destinations: [
{
_id: 0,
airport: 'JFK',
connects: [ 'BOS', 'ORD' ],
numConnections: Long('1')
},
{
_id: 1,
airport: 'BOS',
connects: [ 'JFK', 'PWM' ],
numConnections: Long('0')
},
{
_id: 4,
airport: 'LHR',
connects: [ 'PWM' ],
numConnections: Long('2')
},
{
_id: 3,
airport: 'PWM',
connects: [ 'BOS', 'LHR' ],
numConnections: Long('1')
},
{
_id: 2,
airport: 'ORD',
connects: [ 'JFK' ],
numConnections: Long('2')
}
]
}
]

A tabela a seguir fornece um caminho transversal para a pesquisa recursiva, até a profundidade 2, onde o airport inicial é JFK:

Valor inicial

O valor nearestAirport da coleção travelers:

{ ... nearestAirport: "JFK" }

Profundidade 0

{ _id: 0, airport: "JFK", connects: [ "BOS", "ORD" ] }

Profundidade 1

{ _id: 1, airport: "BOS", connects: [ "JFK", "PWM" ] }
{ _id: 2, airport: "ORD", connects: [ "JFK" ] }

Profundidade 2

{ _id: 3, airport: "PWM", connects: [ "BOS", "LHR" ] }

O exemplo a seguir usa uma coleção com um conjunto de documentos que contêm nomes de pessoas juntamente com arrayes de seus amigos e seus hobbies. Uma operação de agregação encontra uma pessoa em particular e atravessa sua rede de conexões para encontrar pessoas que listam o golf entre seus hobbies.

Uma coleção chamada people contém os seguintes documentos:

db.people.insertMany( [
{
_id: 1,
name: "Tanya Jordan",
friends: [ "Shirley Soto", "Terry Hawkins", "Carole Hale" ],
hobbies: [ "tennis", "unicycling", "golf" ]
},
{
_id: 2,
name: "Carole Hale",
friends: [ "Joseph Dennis", "Tanya Jordan", "Terry Hawkins" ],
hobbies: [ "archery", "golf", "woodworking" ]
},
{
_id: 3,
name: "Terry Hawkins",
friends: [ "Tanya Jordan", "Carole Hale", "Angelo Ward" ],
hobbies: [ "knitting", "frisbee" ]
},
{
_id: 4,
name: "Joseph Dennis",
friends: [ "Angelo Ward", "Carole Hale" ],
hobbies: [ "tennis", "golf", "topiary" ]
},
{
_id: 5,
name: "Angelo Ward",
friends: [ "Terry Hawkins", "Shirley Soto", "Joseph Dennis" ],
hobbies: [ "travel", "ceramics", "golf" ]
},
{
_id: 6,
name: "Shirley Soto",
friends: [ "Angelo Ward", "Tanya Jordan", "Carole Hale" ],
hobbies: [ "frisbee", "set theory" ]
}
] )

A seguinte operação de agregação utiliza três estágios:

  • $match corresponde a documentos com um campo name contendo a string "Tanya Jordan". Retorna um output document.

  • $graphLookup connects the output document's friends field with the name field of other documents in the collection to traverse Tanya Jordan's network of connections. This stage uses the restrictSearchWithMatch parameter to find only documents in which the hobbies array contains golf. Returns one output document.

  • $project molda o documento de saída. Os nomes listados em connections who play golf são retirados do campo name dos documentos listados na array golfers do documento de entrada.

db.people.aggregate( [
{ $match: { "name": "Tanya Jordan" } },
{ $graphLookup: {
from: "people",
startWith: "$friends",
connectFromField: "friends",
connectToField: "name",
as: "golfers",
restrictSearchWithMatch: { "hobbies": "golf" }
}
},
{ $project: {
"name": 1,
"friends": 1,
"connections who play golf": "$golfers.name"
}
}
] )
[
{
_id: 1,
name: 'Tanya Jordan',
friends: [ 'Shirley Soto', 'Terry Hawkins', 'Carole Hale' ],
'connections who play golf': [
'Tanya Jordan',
'Joseph Dennis',
'Angelo Ward',
'Carole Hale'
]
}
]

Uma coleção chamada employees possui os seguintes documentos:

{ _id: 1, name: "Dev" },
{ _id: 2, name: "Eliot", reportsTo: "Dev" },
{ _id: 3, name: "Ron", reportsTo: "Eliot" },
{ _id: 4, name: "Andrew", reportsTo: "Eliot" },
{ _id: 5, name: "Asya", reportsTo: "Ron" },
{ _id: 6, name: "Dan", reportsTo: "Andrew" }

Os seguintes documentos de modelos de classe Employee na coleção employees:

[BsonIgnoreExtraElements]
public class Employee
{
[BsonId]
public int Id { get; set; }
[BsonElement("name")]
public string Name { get; set; } = null!;
[BsonElement("reportsTo")]
public string? ReportsTo { get; set; }
[BsonElement("hobbies")]
public List<string> Hobbies { get; set; } = new();
[BsonElement("reportingHierarchy")]
public List<Employee> ReportingHierarchy { get; set; } = new();
}

To use the MongoDB .NET/C# driver to add a $graphLookup stage to an aggregation pipeline, call the UnionWith() method on a PipelineDefinition object.

O exemplo a seguir cria um estágio de pipeline que corresponde recursivamente aos campos ReportsTo e Name na collection employees, retornando a hierarquia de relatórios para cada pessoa:

var pipeline = new EmptyPipelineDefinition<Employee>()
.GraphLookup<Employee, Employee, Employee, string, string, string, List<Employee>, Employee>(
from: _collection,
connectFromField: e => e.ReportsTo!,
connectToField: e => e.Name,
startWith: e => e.ReportsTo!,
@as: e => e.ReportingHierarchy);

You can use an AggregateGraphLookupOptions object to specify the depth to recurse and the name of the depth field. The following code example performs the same $graphLookup operation as the previous example, but specifies a maximum recursion depth of 1:

var pipeline = new EmptyPipelineDefinition<Employee>()
.GraphLookup<Employee, Employee, Employee, string, string, string, List<Employee>, Employee>(
from: _collection,
connectFromField: e => e.ReportsTo!,
connectToField: e => e.Name,
startWith: e => e.ReportsTo!,
@as: e => e.ReportingHierarchy,
new AggregateGraphLookupOptions<Employee, Employee, Employee>
{
MaxDepth = 1
});

Você também pode usar um objeto AggregateGraphLookupOptions para especificar um filtro ao qual os documentos devem corresponder para que o MongoDB os inclua em sua pesquisa. O exemplo de código a seguir executa a mesma operação $graphLookup dos exemplos anteriores, mas inclui somente documentos Employee em que o campo Hobbies contém "golf":

var pipeline = new EmptyPipelineDefinition<Employee>()
.GraphLookup<Employee, Employee, Employee, string, string, string, List<Employee>, Employee>(
from: _collection,
connectFromField: e => e.ReportsTo!,
connectToField: e => e.Name,
startWith: e => e.ReportsTo!,
@as: e => e.ReportingHierarchy,
new AggregateGraphLookupOptions<Employee, Employee, Employee>
{
MaxDepth = 1,
RestrictSearchWithMatch = Builders<Employee>.Filter.AnyEq(
e => e.Hobbies, "golf")
});

Uma coleção chamada employees possui os seguintes documentos:

db.employees.insertMany([
{ _id: 1, name: "Dev" },
{ _id: 2, name: "Eliot", reportsTo: "Dev" },
{ _id: 3, name: "Ron", reportsTo: "Eliot" },
{ _id: 4, name: "Andrew", reportsTo: "Eliot" },
{ _id: 5, name: "Asya", reportsTo: "Ron" },
{ _id: 6, name: "Dan", reportsTo: "Andrew" }
]);

Para usar o driver Node.js do MongoDB para adicionar um estágio $graphLookup a um pipeline de agregação , use o operador $graphLookup em um objeto de pipeline.

O exemplo a seguir cria um estágio de pipeline que combina recursivamente os campos reportsTo aos campos name na coleção employees, retornando a hierarquia de relatórios para cada pessoa em um novo campo chamado reportingHierarchy. O exemplo em seguida executa o pipeline de agregação:

const pipeline = [
{
$graphLookup: {
from: "employees",
connectFromField: "reportsTo",
connectToField: "name",
startWith: "$reportsTo",
as: "reportingHierarchy"
}
}
];
const cursor = collection.aggregate(pipeline);
return cursor;

Para especificar a profundidade da recursão, utilize o campo maxDepth. O exemplo de código a seguir realiza a mesma operação $graphLookup que o exemplo anterior, mas define uma profundidade máxima de recursão de 1:

const pipeline = [
{
$graphLookup: {
from: "employees",
connectFromField: "reportsTo",
connectToField: "name",
startWith: "$reportsTo",
as: "reportingHierarchy",
maxDepth: 1
}
}
];
const cursor = collection.aggregate(pipeline);
return cursor;

Para especificar um filtro que os documentos devem corresponder para que a operação os inclua nos resultados da pesquisa, use o campo restrictSearchWithMatch. O exemplo de código a seguir realiza a mesma operação $graphLookup que os exemplos anteriores, mas inclui apenas os documentos employee em que o campo hobbies contém "golf":

const pipeline = [
{
$graphLookup: {
from: "employees",
connectFromField: "reportsTo",
connectToField: "name",
startWith: "$reportsTo",
as: "reportingHierarchy",
maxDepth: 1,
restrictSearchWithMatch: { hobbies: "golf" }
}
}
];
const cursor = collection.aggregate(pipeline);
return cursor;

To learn more about how to use $graphLookup, see Working with Graph Data in MongoDB.