

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# $graphLookup
<a name="graphLookup"></a>

Novo na versão 8.0.2.

O estágio `$graphLookup` de agregação no Amazon DocumentDB realiza uma pesquisa recursiva em uma coleção. Para cada documento de entrada, `$graphLookup` começa com um ou mais valores e combina repetidamente um campo de conexão com um campo de destino, seguindo a cadeia de documentos correspondentes até que não haja mais correspondências ou uma profundidade de recursão opcional seja alcançada. Isso é útil para percorrer dados hierárquicos ou semelhantes a gráficos, como estruturas de relatórios organizacionais, árvores de categorias ou relacionamentos de rede.

**Parâmetros**
+ `from`: A coleção de destino a ser pesquisada recursivamente. A `from` coleção deve estar no mesmo banco de dados.
+ `startWith`: a expressão que especifica o valor ou valores com os quais iniciar a pesquisa recursiva. Esse valor é comparado com o `connectToField` dos documentos na `from` coleção. Se for `startWith` avaliada como uma matriz, a pesquisa será executada em todos os elementos da matriz ao mesmo tempo.
+ `connectFromField`: o nome do campo cujo valor é usado para se conectar ao próximo documento na pesquisa recursiva. Se o valor for uma matriz, cada elemento será seguido individualmente pela travessia.
+ `connectToField`: o nome do campo na `from` coleção que é comparado com o valor do`connectFromField`.
+ `as`: o nome do campo de matriz adicionado a cada documento de saída. Esse campo contém os documentos encontrados durante a pesquisa recursiva. Para obter informações sobre a ordem desses documentos, consulte o item Ordenação de resultados na seção Comportamento a seguir.
+ `maxDepth`: um número inteiro não negativo que especifica o número máximo de iterações recursivas a serem executadas após a pesquisa inicial. Esse parâmetro é opcional. Um valor de `0` executa somente a correspondência inicial e nenhuma recursão. Se você omitir`maxDepth`, a pesquisa continuará recursivamente até que não haja mais documentos correspondentes.
+ `depthField`: o nome do campo a ser adicionado a cada documento na `as` matriz que contém a profundidade de recursão na qual o documento foi encontrado. Esse parâmetro é opcional. A profundidade é representada como a `NumberLong` e começa em zero, então a pesquisa inicial corresponde a uma profundidade de`0`.
+ `restrictSearchWithMatch`: um documento que especifica uma condição de correspondência adicional aplicada aos documentos da pesquisa. Esse parâmetro é opcional. A condição usa a mesma sintaxe de consulta como um `$match` estágio e não pode incluir expressões de agregação.

**nota**  
O `$graphLookup` palco está sujeito a um limite de memória de 100 MB e não suporta`allowDiskUse:true`. Uma operação que excede esse limite retorna um erro. Se a agregação incluir outros estágios, a `allowDiskUse:true` opção permanecerá em vigor para esses estágios.

**Comportamento**
+ **Cross-collection traversal**: `from` defina a coleção que você deseja pesquisar. Essa pode ser a mesma coleção em que o pipeline é executado ou uma coleção diferente no mesmo banco de dados.
+ **Ordenação dos resultados**: os documentos na `as` matriz não são retornados em nenhuma ordem garantida.

## Exemplo (MongoDB Shell)
<a name="graphLookup-examples"></a>

O exemplo a seguir é usado `$graphLookup` para percorrer uma hierarquia de relatórios de funcionários e, para cada funcionário, colocar toda a cadeia de gerentes acima deles.

Os comandos a seguir, executados no shell mongosh, inserem exemplos de documentos de funcionários que estabelecem uma hierarquia de relatórios:

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

A agregação a seguir retorna a cadeia de gerenciamento completa de cada funcionário em uma nova `reportingHierarchy` matriz:

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

Essa operação retorna a seguinte saída:

```
[
  {
    _id: 1,
    name: 'Dev',
    reportsTo: 'Eliot',
    reportingHierarchy: [
      { _id: 2, name: 'Eliot', reportsTo: 'Ron', level: 0 },
      { _id: 3, name: 'Ron', reportsTo: 'Andrew', level: 1 },
      { _id: 4, name: 'Andrew', reportsTo: 'Asya', level: 2 },
      { _id: 5, name: 'Asya', level: 3 }
    ]
  },
  {
    _id: 2,
    name: 'Eliot',
    reportsTo: 'Ron',
    reportingHierarchy: [
      { _id: 3, name: 'Ron', reportsTo: 'Andrew', level: 0 },
      { _id: 4, name: 'Andrew', reportsTo: 'Asya', level: 1 },
      { _id: 5, name: 'Asya', level: 2 }
    ]
  },
  {
    _id: 3,
    name: 'Ron',
    reportsTo: 'Andrew',
    reportingHierarchy: [
      { _id: 4, name: 'Andrew', reportsTo: 'Asya', level: 0 },
      { _id: 5, name: 'Asya', level: 1 }
    ]
  },
  {
    _id: 4,
    name: 'Andrew',
    reportsTo: 'Asya',
    reportingHierarchy: [
      { _id: 5, name: 'Asya', level: 0 }
    ]
  },
  {
    _id: 5,
    name: 'Asya',
    reportingHierarchy: []
  }
]
```

Cada documento do funcionário ganha uma `reportingHierarchy` matriz que contém os documentos do gerente correspondentes recursivamente. O `level` campo registra a profundidade da recursão na qual cada gerente foi encontrado. Asya não tem `reportsTo` valor, então sua `reportingHierarchy` matriz está vazia.

## Exemplo com maxDepth e restrict SearchWithMatch (MongoDB Shell)
<a name="graphLookup-filter-depth-example"></a>

O exemplo a seguir percorre uma rede de conexões entre pessoas e usuários `maxDepth` para limitar a recursão e incluir somente documentos que correspondam `restrictSearchWithMatch` a uma condição adicional. A pesquisa encontra as conexões de uma pessoa inicial, com até dois níveis de profundidade, mantendo apenas as pessoas cuja `hobbies` matriz contém`golf`.

Os comandos a seguir, executados no shell mongosh, inserem exemplos de documentos nos quais cada pessoa `friends` aponta para frente por meio de uma cadeia unidirecional de conexões:

```
db.people.insertMany([
  { _id: 1, name: "Tanya", friends: [ "Carole", "Shirley" ], hobbies: [ "tennis", "golf" ] },
  { _id: 2, name: "Carole", friends: [ "Joseph" ], hobbies: [ "archery", "golf" ] },
  { _id: 3, name: "Joseph", friends: [ "Angelo" ], hobbies: [ "tennis", "golf" ] },
  { _id: 4, name: "Angelo", friends: [ "Miguel" ], hobbies: [ "travel", "golf" ] },
  { _id: 5, name: "Miguel", friends: [], hobbies: [ "golf" ] },
  { _id: 6, name: "Shirley", friends: [], hobbies: [ "frisbee" ] }
]);
```

A agregação a seguir começa com Tanya, percorre sua rede de conexões com até dois níveis de profundidade e mantém apenas as pessoas que `golf` listam como hobby:

```
db.people.aggregate([
  { $match: { name: "Tanya" } },
  {
    $graphLookup: {
      from: "people",
      startWith: "$friends",
      connectFromField: "friends",
      connectToField: "name",
      as: "golfConnections",
      maxDepth: 2,
      restrictSearchWithMatch: { hobbies: "golf" }
    }
  },
  { $project: { name: 1, "golfConnections.name": 1 } }
]);
```

Essa operação retorna a seguinte saída:

```
[
  {
    _id: 1,
    name: 'Tanya',
    golfConnections: [
      { name: 'Carole' },
      { name: 'Joseph' },
      { name: 'Angelo' }
    ]
  }
]
```

Somente as conexões cuja `hobbies` matriz contém `golf` são incluídas e a travessia é interrompida após dois níveis de recursão. Shirley é excluída porque ela não lista`golf`, e Miguel é excluído porque está a três níveis de distância de Tanya, além do de. `maxDepth` `2` Como as conexões formam uma cadeia unidirecional que nunca aponta para Tanya, o documento inicial não é correspondido durante a pesquisa recursiva.

## Exemplos de código
<a name="graphLookup-code"></a>

Para ver um exemplo de código que cria a hierarquia de relatórios de funcionários a partir do primeiro exemplo usando um driver MongoDB, escolha a guia do idioma que você deseja usar:

------
#### [ Node.js ]

```
const { MongoClient } = require('mongodb');

async function example() {
  const client = new MongoClient('mongodb://<username>:<password>@<cluster-endpoint>:27017/?tls=true&tlsCAFile=global-bundle.pem&replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false');

  try {
    await client.connect();
    const db = client.db('test');
    const employees = db.collection('employees');

    const result = await employees.aggregate([
      {
        $graphLookup: {
          from: 'employees',
          startWith: '$reportsTo',
          connectFromField: 'reportsTo',
          connectToField: 'name',
          as: 'reportingHierarchy',
          depthField: 'level'
        }
      }
    ]).toArray();

    console.log(JSON.stringify(result, null, 2));
  } catch (err) {
    console.error('Failed to run $graphLookup aggregation:', err.message);
  } finally {
    await client.close();
  }
}

example();
```

------
#### [ Python ]

```
from pymongo import MongoClient
from pymongo.errors import PyMongoError

def example():
    client = MongoClient('mongodb://<username>:<password>@<cluster-endpoint>:27017/?tls=true&tlsCAFile=global-bundle.pem&replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false')

    try:
        db = client['test']
        employees = db['employees']

        pipeline = [
            {
                "$graphLookup": {
                    "from": "employees",
                    "startWith": "$reportsTo",
                    "connectFromField": "reportsTo",
                    "connectToField": "name",
                    "as": "reportingHierarchy",
                    "depthField": "level"
                }
            }
        ]

        result = list(employees.aggregate(pipeline))

        for doc in result:
            print(doc)
    except PyMongoError as error:
        print(f"Failed to run $graphLookup aggregation: {error}")
    finally:
        client.close()

example()
```

------