Menu Docs
Página inicial do Docs
/
Manual do MongoDB
/ / /

$graphLookup (agregação)

Nesta página

  • Definição
  • Considerações
  • Exemplos
  • Recurso adicional
$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

Coleção de destino para a operação $graphLookup a ser pesquisada, combinando recursivamente o connectFromField com o connectToField. A coleção from deve estar no mesmo banco de dados que quaisquer outras coleções utilizadas na operação.

A partir do MongoDB 5.1, a coleção especificada no parâmetro from pode ser fragmentada.

startWith
Expressão que especifica o valor do connectFromField com o qual iniciar a pesquisa recursiva. Opcionalmente, startWith pode ser um conjunto de valores, cada um dos quais é seguido individualmente através do processo transversal.
connectFromField
Nome do campo cujo valor $graphLookup usa para corresponder recursivamente ao connectToField de outros documentos na coleção. Se o valor for um array, cada elemento será seguido individualmente durante o processo transversal.
connectToField
Nome do campo em outros documentos para corresponder ao valor do campo especificado pelo parâmetro connectFromField.
as

Nome do campo de array adicionado a cada documento de saída. Contém os documentos percorridos no estágio $graphLookup para chegar ao documento.

Observação

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.

Observação

Você não pode utilizar qualquer expressão de agregação neste filtro. Por exemplo, um documento de consulta como

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

não funcionará neste contexto para encontrar documentos em que o valor lastName seja diferente do valor lastName do documento de entrada, porque "$lastName" atuará como um literal de string, não como um caminho de campo.

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

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

Definir o campo maxDepth com 0 equivale a um estágio da pesquisa $graphLookup não recursiva.

A etapa $graphLookup deve permanecer dentro do limite de memória de 100 megabytes. Se o allowDiskUse: true for especificado para a operação aggregate(), a etapa $graphLookup ignorará a opção. Se houver outras etapas na operação do aggregate(), a opção allowDiskUse: true estará em vigor para estas outras etapas.

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

Se estiver realizando uma agregação que envolva várias exibições, como com $lookup ou $graphLookup, as exibições deverão ter o mesmo agrupamento.

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

A seguinte operação $graphLookup corresponde recursivamente nos campos reportsTo e name na coleção employees, retornando a hierarquia de relatórios de cada pessoa:

db.employees.aggregate( [
{
$graphLookup: {
from: "employees",
startWith: "$reportsTo",
connectFromField: "reportsTo",
connectToField: "name",
as: "reportingHierarchy"
}
}
] )

A operação retorna o seguinte:

{
"_id" : 1,
"name" : "Dev",
"reportingHierarchy" : [ ]
}
{
"_id" : 2,
"name" : "Eliot",
"reportsTo" : "Dev",
"reportingHierarchy" : [
{ "_id" : 1, "name" : "Dev" }
]
}
{
"_id" : 3,
"name" : "Ron",
"reportsTo" : "Eliot",
"reportingHierarchy" : [
{ "_id" : 1, "name" : "Dev" },
{ "_id" : 2, "name" : "Eliot", "reportsTo" : "Dev" }
]
}
{
"_id" : 4,
"name" : "Andrew",
"reportsTo" : "Eliot",
"reportingHierarchy" : [
{ "_id" : 1, "name" : "Dev" },
{ "_id" : 2, "name" : "Eliot", "reportsTo" : "Dev" }
]
}
{
"_id" : 5,
"name" : "Asya",
"reportsTo" : "Ron",
"reportingHierarchy" : [
{ "_id" : 1, "name" : "Dev" },
{ "_id" : 2, "name" : "Eliot", "reportsTo" : "Dev" },
{ "_id" : 3, "name" : "Ron", "reportsTo" : "Eliot" }
]
}
{
"_id" : 6,
"name" : "Dan",
"reportsTo" : "Andrew",
"reportingHierarchy" : [
{ "_id" : 1, "name" : "Dev" },
{ "_id" : 2, "name" : "Eliot", "reportsTo" : "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.

Como o $lookup, o $graphLookup pode acessar outra coleção no mesmo banco de dados.

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

A operação retorna os seguintes resultados:

{
"_id" : 1,
"name" : "Dev",
"nearestAirport" : "JFK",
"destinations" : [
{ "_id" : 3,
"airport" : "PWM",
"connects" : [ "BOS", "LHR" ],
"numConnections" : NumberLong(2) },
{ "_id" : 2,
"airport" : "ORD",
"connects" : [ "JFK" ],
"numConnections" : NumberLong(1) },
{ "_id" : 1,
"airport" : "BOS",
"connects" : [ "JFK", "PWM" ],
"numConnections" : NumberLong(1) },
{ "_id" : 0,
"airport" : "JFK",
"connects" : [ "BOS", "ORD" ],
"numConnections" : NumberLong(0) }
]
}
{
"_id" : 2,
"name" : "Eliot",
"nearestAirport" : "JFK",
"destinations" : [
{ "_id" : 3,
"airport" : "PWM",
"connects" : [ "BOS", "LHR" ],
"numConnections" : NumberLong(2) },
{ "_id" : 2,
"airport" : "ORD",
"connects" : [ "JFK" ],
"numConnections" : NumberLong(1) },
{ "_id" : 1,
"airport" : "BOS",
"connects" : [ "JFK", "PWM" ],
"numConnections" : NumberLong(1) },
{ "_id" : 0,
"airport" : "JFK",
"connects" : [ "BOS", "ORD" ],
"numConnections" : NumberLong(0) } ]
}
{
"_id" : 3,
"name" : "Jeff",
"nearestAirport" : "BOS",
"destinations" : [
{ "_id" : 2,
"airport" : "ORD",
"connects" : [ "JFK" ],
"numConnections" : NumberLong(2) },
{ "_id" : 3,
"airport" : "PWM",
"connects" : [ "BOS", "LHR" ],
"numConnections" : NumberLong(1) },
{ "_id" : 4,
"airport" : "LHR",
"connects" : [ "PWM" ],
"numConnections" : NumberLong(2) },
{ "_id" : 0,
"airport" : "JFK",
"connects" : [ "BOS", "ORD" ],
"numConnections" : NumberLong(1) },
{ "_id" : 1,
"airport" : "BOS",
"connects" : [ "JFK", "PWM" ],
"numConnections" : NumberLong(0) }
]
}

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:

{
"_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 documento de saída.

  • $graphLookup conecta o campo friends do documento de saída com o campo name de outros documentos na coleção para atravessar a rede de conexões de Tanya Jordan's Esse estágio utiliza o parâmetro restrictSearchWithMatch para encontrar somente documentos nos quais o array hobbies contém golf. Retorna um documento de saída.

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

A operação retorna o seguinte documento:

{
"_id" : 1,
"name" : "Tanya Jordan",
"friends" : [
"Shirley Soto",
"Terry Hawkins",
"Carole Hale"
],
"connections who play golf" : [
"Joseph Dennis",
"Tanya Jordan",
"Angelo Ward",
"Carole Hale"
]
}

Webinar: Trabalhando com dados de gráficos no MongoDB

← $geoNear (agregação)