

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

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

バージョン 8.0.2 の新機能。

Amazon DocumentDB の`$graphLookup`集約ステージは、コレクションに対して再帰的な検索を実行します。各入力ドキュメントについて、 は 1 つ以上の値から`$graphLookup`開始し、接続フィールドをターゲットフィールドに繰り返し一致させ、一致するドキュメントのチェーンに従って、一致するドキュメントがなくなるか、オプションの再帰深度に達します。これは、組織のレポート構造、カテゴリツリー、ネットワーク関係など、グラフのようなデータや階層データをトラバースする場合に便利です。

**パラメータ**
+ `from`: 再帰的に検索するターゲットコレクション。`from` コレクションは同じデータベースに存在する必要があります。
+ `startWith`: 再帰検索を開始する値を指定する式。この値は、`from`コレクション内のドキュメント`connectToField`の と比較されます。が配列に`startWith`評価される場合、検索はすべての配列要素から同時に実行されます。
+ `connectFromField`: 値が再帰検索の次のドキュメントへの接続に使用されるフィールド名。値が配列の場合、各要素はトラバーサルを通じて個別にフォローされます。
+ `connectToField`: の値と一致する`from`コレクション内のフィールド名`connectFromField`。
+ `as`: 各出力ドキュメントに追加された配列フィールドの名前。このフィールドには、再帰検索中に見つかったドキュメントが含まれます。これらのドキュメントの順序については、次の動作セクションの結果の順序付け項目を参照してください。
+ `maxDepth`: 最初のルックアップ後に実行する再帰的反復の最大数を指定する負以外の整数。このパラメータはオプションです。の値は、最初の一致のみ`0`を実行し、再帰は実行しません。を省略すると`maxDepth`、一致するドキュメントがなくなるまで検索が再帰的に続行されます。
+ `depthField`: ドキュメントが見つかった再帰深度を保持する`as`配列内の各ドキュメントに追加するフィールドの名前。このパラメータはオプションです。深さは として表`NumberLong`され、ゼロから始まるため、最初のルックアップは の深さに対応します`0`。
+ `restrictSearchWithMatch`: 検索のドキュメントに適用される追加の一致条件を指定するドキュメント。このパラメータはオプションです。条件は`$match`ステージと同じクエリ構文を使用し、集計式を含めることはできません。

**注記**  
`$graphLookup` ステージには 100 MB のメモリ制限が適用され、 はサポートされていません`allowDiskUse:true`。この制限を超えるオペレーションはエラーを返します。集約に他のステージが含まれている場合、`allowDiskUse:true`オプションはそれらのステージに対して有効です。

**Behavior**
+ **クロスコレクショントラバーサル**: 検索するコレクション`from`に設定します。これは、パイプラインが実行するのと同じコレクションでも、同じデータベース内の別のコレクションでもかまいません。
+ **結果の順序**: `as`配列内のドキュメントは、保証された順序で返されません。

## 例 (MongoDB シェル)
<a name="graphLookup-examples"></a>

次の例では`$graphLookup`、 を使用して従業員レポート階層を横断し、各従業員について、その上のマネージャーチェーン全体を返します。

次のコマンドは、mongosh シェルで実行し、レポート階層を確立するサンプル従業員ドキュメントを挿入します。

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

次の集計は、新しい`reportingHierarchy`配列の各従業員の完全な管理チェーンを返します。

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

このオペレーションは、次の出力を返します。

```
[
  {
    _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: []
  }
]
```

各従業員ドキュメントは、再帰的に一致したマネージャードキュメントを含む`reportingHierarchy`配列を取得します。`level` フィールドには、各マネージャーが見つかった再帰の深さが記録されます。Asya には`reportsTo`値がないため、`reportingHierarchy`配列は空です。

## maxDepth と restrictSearchWithMatch の例 (MongoDB シェル)
<a name="graphLookup-filter-depth-example"></a>

次の例では、人と の間の接続のネットワークを横断し、 `maxDepth` を使用して再帰を制限し`restrictSearchWithMatch`、追加の条件に一致するドキュメントのみを含めます。検索では、開始者の接続が最大 2 レベルまで検索され、`hobbies`配列に が含まれているユーザーのみが保持されます`golf`。

次のコマンドを mongosh シェルで実行し、各ユーザーの`friends`ポイントが 1 方向の接続チェーンを通過するサンプルドキュメントを挿入します。

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

次の集約は、Tanya から始まり、接続のネットワークを最大 2 レベル深く横断し、趣味`golf`としてリストされている人だけを保持します。

```
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 } }
]);
```

このオペレーションは、次の出力を返します。

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

`hobbies` 配列を含む接続のみ`golf`が含まれ、2 レベルの再帰後にトラバーサルが停止します。Shirley は を一覧表示しないため除外され`golf`、Miguel は `maxDepth`の を超えて Tanya から 3 レベル離れているため除外されます`2`。接続は Tanya を指さない一方向チェーンを形成するため、再帰的な検索中に開始ドキュメントは一致しません。

## コードの例
<a name="graphLookup-code"></a>

MongoDB ドライバーを使用して最初の例から従業員レポート階層を構築するコード例を表示するには、使用する言語のタブを選択します。

------
#### [ 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()
```

------