View a markdown version of this page

$graphLookup - Amazon DocumentDB

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

$graphLookup

Nouveau depuis la version 8.0.2.

L'étape $graphLookup d'agrégation d'Amazon DocumentDB effectue une recherche récursive sur une collection. Pour chaque document d'entrée, $graphLookup part d'une ou de plusieurs valeurs et fait correspondre à plusieurs reprises un champ de connexion à un champ cible, en suivant la chaîne des documents correspondants jusqu'à ce qu'il n'y ait plus de correspondance ou qu'une profondeur de récursivité facultative soit atteinte. Cela est utile pour parcourir des données de type graphique ou hiérarchiques, telles que des structures hiérarchiques organisationnelles, des arbres de catégories ou des relations entre réseaux.

Paramètres

  • from: collection cible à rechercher de manière récursive. La from collection doit se trouver dans la même base de données.

  • startWith: expression qui spécifie la ou les valeurs avec lesquelles commencer la recherche récursive. Cette valeur est comparée à celle connectToField des documents de la from collection. Si startWith l'évaluation porte sur un tableau, la recherche est exécutée à partir de tous les éléments du tableau en même temps.

  • connectFromField: nom du champ dont la valeur est utilisée pour se connecter au document suivant dans la recherche récursive. Si la valeur est un tableau, chaque élément est suivi individuellement tout au long de la traversée.

  • connectToField: nom du champ de la from collection qui correspond à la valeur duconnectFromField.

  • as: nom du champ de tableau ajouté à chaque document de sortie. Ce champ contient les documents trouvés lors de la recherche récursive. Pour plus d'informations sur l'ordre de ces documents, consultez l'élément Ordre des résultats dans la section Comportement suivante.

  • maxDepth: entier non négatif qui spécifie le nombre maximum d'itérations récursives à effectuer après la recherche initiale. Ce paramètre est facultatif. Une valeur de 0 effectue uniquement la correspondance initiale et aucune récursivité. Si vous omettezmaxDepth, la recherche se poursuit de manière récursive jusqu'à ce qu'il n'y ait plus de documents correspondants.

  • depthField: nom du champ à ajouter à chaque document du as tableau contenant la profondeur de récursivité à laquelle le document a été trouvé. Ce paramètre est facultatif. La profondeur est représentée par un NumberLong et commence à zéro, de sorte que la recherche initiale correspond à une profondeur de0.

  • restrictSearchWithMatch: document qui spécifie une condition de correspondance supplémentaire appliquée aux documents de la recherche. Ce paramètre est facultatif. La condition utilise la même syntaxe de requête qu'une $match étape et ne peut pas inclure d'expressions d'agrégation.

Note

Le $graphLookup stage est soumis à une limite de mémoire de 100 Mo et n'est pas compatibleallowDiskUse:true. Une opération dépassant cette limite renvoie une erreur. Si l'agrégation inclut d'autres étapes, l'allowDiskUse:trueoption reste en vigueur pour ces étapes.

Comportement

  • Cross-collection traversal  : définissez from la collection dans laquelle vous souhaitez effectuer la recherche. Il peut s'agir de la même collection que celle utilisée par le pipeline ou d'une collection différente dans la même base de données.

  • Ordre des résultats  : Les documents du as tableau ne sont pas renvoyés dans un ordre garanti.

Exemple (MongoDB Shell)

L'exemple suivant permet $graphLookup de parcourir la hiérarchie de reporting d'un employé et, pour chaque employé, de renvoyer la chaîne complète des responsables au-dessus de lui.

Les commandes suivantes, exécutées dans le shell Mongosh, insèrent des exemples de documents relatifs aux employés qui établissent une hiérarchie de rapports :

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

L'agrégation suivante renvoie la chaîne de gestion complète pour chaque employé dans un nouveau reportingHierarchy tableau :

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

Cette opération renvoie le résultat suivant :

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

Chaque document d'employé obtient un reportingHierarchy tableau contenant les documents de gestion correspondants de manière récursive. Le level champ enregistre la profondeur de récursivité à laquelle chaque responsable a été trouvé. Asya n'a aucune reportsTo valeur, donc son reportingHierarchy tableau est vide.

Exemple avec MaxDepth et restrict SearchWithMatch (MongoDB Shell)

L'exemple suivant parcourt un réseau de connexions entre des personnes et des utilisateurs maxDepth afin de limiter la récursivité et d'inclure uniquement les documents qui répondent restrictSearchWithMatch à une condition supplémentaire. La recherche trouve les connexions d'une personne de départ, jusqu'à deux niveaux de profondeur, en ne conservant que les personnes dont le hobbies tableau contientgolf.

Les commandes suivantes, exécutées dans le shell mongosh, insèrent des exemples de documents dans lesquels chaque personne friends pointe vers l'avant via une chaîne de connexions unidirectionnelle :

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

L'agrégation suivante part de Tanya, parcourt son réseau de connexions jusqu'à deux niveaux de profondeur et ne conserve que les personnes qui les listent golf comme passe-temps :

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

Cette opération renvoie le résultat suivant :

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

Seules les connexions dont le hobbies tableau contient golf sont incluses, et la traversée s'arrête après deux niveaux de récursivité. Shirley est exclue parce qu'elle ne figure pas sur la listegolf, et Miguel est exclu parce qu'il est à trois niveaux de Tanya, au-delà du maxDepth « of ». 2 Comme les connexions forment une chaîne unidirectionnelle qui ne pointe jamais vers Tanya, le document de départ n'est pas mis en correspondance lors de la recherche récursive.

Exemples de code

Pour afficher un exemple de code qui construit la hiérarchie des rapports des employés à partir du premier exemple à l'aide d'un pilote MongoDB, choisissez l'onglet correspondant à la langue que vous souhaitez utiliser :

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()