Cambiado en la versión 3.4.
Definición
$graphLookupRealiza una búsqueda recursiva en una colección, con opciones para restringir la búsqueda por profundidad de recursión y filtro de query.
El proceso de búsqueda
$graphLookupse resume a continuación:Los documentos de entrada fluyen a la etapa
$graphLookupde una operación de agregación.$graphLookupdirige la búsqueda a la colección designada por el parámetrofrom(consulte a continuación la lista completa de parámetros de búsqueda).Para cada documento de entrada, la búsqueda comienza con el valor designado por
startWith.$graphLookupcompara el valorstartWithcon el campo designado porconnectToFielden otros documentos de la colecciónfrom.Para cada documento coincidente,
$graphLookuptoma el valor deconnectFromFieldy verifica cada documento en la colecciónfrompara un valor deconnectToFieldcoincidente. Para cada coincidencia,$graphLookupagrega el documento coincidente de la colecciónfroma un campo de arreglo nombrado por el parámetroas.Este paso continúa de forma recursiva hasta que no se encuentren más documentos coincidentes o hasta que la operación alcance una profundidad de recursión especificada por el parámetro
maxDepth.$graphLookupluego agrega el campo del arreglo al documento de entrada.$graphLookupdevuelve resultados después de completar su búsqueda en todos los documentos de entrada.
$graphLookuptiene el siguiente prototipo:{ $graphLookup: { from: <collection>, startWith: <expression>, connectFromField: <string>, connectToField: <string>, as: <string>, maxDepth: <number>, depthField: <string>, restrictSearchWithMatch: <document> } } $graphLookuptoma un documento con los siguientes campos:CampoDescripciónfromColección de objetivos para el
$graphLookupOperación para buscar, haciendo coincidir recursivamenteconnectFromFieldconnectToFieldcon. Lafromcolección no se puede fragmentar y debe estar en la misma base de datos que cualquier otra colección utilizada en la operación. Para más información, consulte Colecciones fragmentadas.startWithExpresión que especifica el valor de
connectFromFieldcon el que se inicia la búsqueda recursiva. Opcionalmente,startWithpuede ser una matriz de valores, cada uno de los cuales se sigue individualmente durante el recorrido.connectFromFieldNombre del campo cuyo valor
$graphLookupse utiliza para hacer coincidir recursivamente con elconnectToFieldde otros documentos en la colección. Si el valor es un arreglo, cada elemento se sigue individualmente a través del proceso de recorrido.connectToFieldNombre del campo en otros documentos con el que se debe comparar el valor del campo especificado por el parámetro
connectFromField.asNombre del campo de arreglo añadido a cada documento de salida. Contiene los documentos que se han recorrido en la etapa
$graphLookuppara llegar al documento.No se ofrecen garantías de que los documentos devueltos en el campo
asestén en ningún orden específico.maxDepthOpcional. Número entero no negativo que especifica la profundidad máxima de recursión.
depthFieldOpcional. Nombre del campo que se debe añadir a cada documento recorrido en la ruta de búsqueda. El valor de este campo es la profundidad de recursión del documento, representado como un
NumberLong. El valor de la profundidad de recursión comienza en cero, por lo que la primera búsqueda corresponde a una profundidad de cero.restrictSearchWithMatchOpcional. Un documento que especifica condiciones adicionales para la búsqueda recursiva. La sintaxis es idéntica a la sintaxis de filtro de query.
No se puede usar ninguna expresión de agregación en este filtro. Por ejemplo, no puede utilizar el siguiente documento para encontrar documentos en los que el valor
lastNamesea distinto del valorlastNamedel documento de entrada:{ lastName: { $ne: "$lastName" } } No se puede utilizar el documento en este contexto, porque
"$lastName"actuará como un literal de string, no como una ruta de campo.
Considerations
Colecciones fragmentadas
La colección especificada en from no se puede particionar. Sin embargo, la colección en la que se ejecuta el método aggregate() puede ser particionada. Es decir, en lo siguiente:
db.collection.aggregate([ { $graphLookup: { from: "fromCollection", ... } } ])
El
collectionse puede fragmentar.El
fromCollectionno se puede fragmentar.
Para unir múltiples colecciones fragmentadas, considere lo siguiente:
Modificar las aplicaciones cliente para realizar búsquedas manuales en lugar de utilizar la
$graphLookupetapa de agregación.Si es posible, utilice un modelo de datos integrado que elimine la necesidad de unir colecciones.
Profundidad máxima
Configurar el campo maxDepth a 0 es equivalente a una etapa de búsqueda no recursiva $graphLookup.
Memoria
La etapa debe mantenerse dentro $graphLookup del 100 límite de memoria de megabytes. Si allowDiskUse: true se especifica para la aggregate() operación, la etapa ignora la opción.$graphLookup aggregate() SiallowDiskUse: true hay otras etapas en la operación, la opción se aplica a estas.
Consulte las limitaciones del pipeline de agregación para obtener más información.
Vistas e intercalación
Si se realiza una agregación que implique varias vistas, como con $lookup o $graphLookup, las vistas deben tener la misma intercalación.
Ejemplos
Dentro de una única colección
Una colección llamada employees tiene los siguientes 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" } ] )
La siguiente operación $graphLookup coincide de forma recursiva en los campos reportsTo y name de la colección employees, devolviendo la jerarquía de reportes para cada persona:
db.employees.aggregate( [ { $graphLookup: { from: "employees", startWith: "$reportsTo", connectFromField: "reportsTo", connectToField: "name", as: "reportingHierarchy" } } ] )
La operación devuelve lo siguiente:
{ _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: 4, name: "Andrew", reportsTo: "Eliot" }, { _id: 2, name: "Eliot", reportsTo: "Dev" }, { _id: 1, name: "Dev" } ] }
La siguiente tabla proporciona una ruta de acceso para el documento { "_id" : 5, "name" : "Asya", "reportsTo" : "Ron" }:
Valor inicial | El valor | |
Profundidad 0 | | |
Profundidad 1 | | |
Profundidad 2 | |
El resultado genera la jerarquía Asya -> Ron -> Eliot -> Dev.
A través de múltiples colecciones
Al igual que $lookup, $graphLookup puede acceder a otra colección en la misma base de datos.
Por ejemplo, se puede crear una base de datos con dos colecciones:
Una colección
airportscon los siguientes 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" ] } ] ) Una colección
travelerscon los siguientes 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 en la colección travelers, la siguiente operación de agregación busca el valor nearestAirport en la colección airports y coincide recursivamente el campo connects con el campo airport. La operación especifica una profundidad máxima de recursión de 2.
db.travelers.aggregate( [ { $graphLookup: { from: "airports", startWith: "$nearestAirport", connectFromField: "connects", connectToField: "airport", maxDepth: 2, depthField: "numConnections", as: "destinations" } } ] )
La operación devuelve los siguientes 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) } ] }
La siguiente tabla proporciona una ruta de recorrido para la búsqueda recursiva, hasta la profundidad 2, donde el airport inicial es JFK:
Valor inicial | El valor | ||
Profundidad 0 | | ||
Profundidad 1 | | ||
Profundidad 2 | |
Con un filtro de query
El siguiente ejemplo utiliza una colección con un conjunto de documentos que contienen nombres de personas junto con arreglos de sus amigos y sus aficiones. Una operación de agregación encuentra a una persona en particular y recorre su red de conexiones para encontrar personas que incluyan golf entre sus aficiones.
Una colección llamada people contiene los siguientes 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" ] } ] )
La siguiente operación de agregación utiliza tres etapas:
$matchcoincide en documentos con un camponameque contiene la string"Tanya Jordan". Devuelve un documento de salida.$graphLookupconecta el campofriendsdel documento de salida con el camponamede otros documentos de la colección para recorrer la red de conexionesTanya Jordan's. Esta etapa utiliza el parámetrorestrictSearchWithMatchpara encontrar solo documentos en los que el arreglohobbiescontienegolf. Devuelve un documento de salida.$projectda forma al documento de salida. Los nombres listados enconnections who play golfse extraen del camponamede los documentos enumerados en el arreglogolfersdel 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" } } ] )
La operación devuelve el siguiente 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" ] }