Docs Menu
Docs Home
/ /
Etapas de la pipeline de agregación

$graphLookup (agregación)

Cambiado en la versión 3.4.

$graphLookup

Realiza 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 $graphLookup se resume a continuación:

  1. Los documentos de entrada fluyen a la etapa $graphLookup de una operación de agregación.

  2. $graphLookup dirige la búsqueda a la colección designada por el parámetro from (consulte a continuación la lista completa de parámetros de búsqueda).

  3. Para cada documento de entrada, la búsqueda comienza con el valor designado por startWith.

  4. $graphLookup compara el valor startWith con el campo designado por connectToField en otros documentos de la colección from.

  5. Para cada documento coincidente, $graphLookup toma el valor de connectFromField y verifica cada documento en la colección from para un valor de connectToField coincidente. Para cada coincidencia, $graphLookup agrega el documento coincidente de la colección from a un campo de arreglo nombrado por el parámetro as.

    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. $graphLookup luego agrega el campo del arreglo al documento de entrada. $graphLookup devuelve resultados después de completar su búsqueda en todos los documentos de entrada.

$graphLookup tiene el siguiente prototipo:

{
$graphLookup: {
from: <collection>,
startWith: <expression>,
connectFromField: <string>,
connectToField: <string>,
as: <string>,
maxDepth: <number>,
depthField: <string>,
restrictSearchWithMatch: <document>
}
}

$graphLookup toma un documento con los siguientes campos:

Campo
Descripción

from

Colección de objetivos para el $graphLookup Operación para buscar, haciendo coincidir recursivamente connectFromField connectToFieldcon. La from colecció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.

startWith

Expresión que especifica el valor de connectFromField con el que se inicia la búsqueda recursiva. Opcionalmente, startWith puede ser una matriz de valores, cada uno de los cuales se sigue individualmente durante el recorrido.

connectFromField

Nombre del campo cuyo valor $graphLookup se utiliza para hacer coincidir recursivamente con el connectToField de otros documentos en la colección. Si el valor es un arreglo, cada elemento se sigue individualmente a través del proceso de recorrido.

connectToField

Nombre del campo en otros documentos con el que se debe comparar el valor del campo especificado por el parámetro connectFromField.

as

Nombre del campo de arreglo añadido a cada documento de salida. Contiene los documentos que se han recorrido en la etapa $graphLookup para llegar al documento.

No se ofrecen garantías de que los documentos devueltos en el campo as estén en ningún orden específico.

maxDepth

Opcional. Número entero no negativo que especifica la profundidad máxima de recursión.

depthField

Opcional. 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.

restrictSearchWithMatch

Opcional. 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 lastName sea distinto del valor lastName del 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.

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 collection se puede fragmentar.

  • El fromCollection no 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 $graphLookup etapa de agregación.

  • Si es posible, utilice un modelo de datos integrado que elimine la necesidad de unir colecciones.

Configurar el campo maxDepth a 0 es equivalente a una etapa de búsqueda no recursiva $graphLookup.

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.

Si se realiza una agregación que implique varias vistas, como con $lookup o $graphLookup, las vistas deben tener la misma intercalació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 reportsTo del documento:

{ ... reportsTo: "Ron" }

Profundidad 0

{ _id: 3, name: "Ron", reportsTo: "Eliot" }

Profundidad 1

{ _id: 2, name: "Eliot", reportsTo: "Dev" }

Profundidad 2

{ _id: 1, name: "Dev" }

El resultado genera la jerarquía Asya -> Ron -> Eliot -> Dev.

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 airports con 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 travelers con 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 nearestAirport de la colección travelers:

{ ... nearestAirport: "JFK" }

Profundidad 0

{ _id: 0, airport: "JFK", connects: [ "BOS", "ORD" ] }

Profundidad 1

{ _id: 1, airport: "BOS", connects: [ "JFK", "PWM" ] }
{ _id: 2, airport: "ORD", connects: [ "JFK" ] }

Profundidad 2

{ _id: 3, airport: "PWM", connects: [ "BOS", "LHR" ] }

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:

  • $match coincide en documentos con un campo name que contiene la string "Tanya Jordan". Devuelve un documento de salida.

  • $graphLookup conecta el campo friends del documento de salida con el campo name de otros documentos de la colección para recorrer la red de conexiones Tanya Jordan's. Esta etapa utiliza el parámetro restrictSearchWithMatch para encontrar solo documentos en los que el arreglo hobbies contiene golf. Devuelve un documento de salida.

  • $project da forma al documento de salida. Los nombres listados en connections who play golf se extraen del campo name de los documentos enumerados en el arreglo golfers del 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"
]
}

Seminario web: Trabajar con datos gráficos en MongoDB

Volver

$geoNear

En esta página