En esta página se describe cómo trabajar con rutas de grafos en Spanner Graph.
En las bases de datos de grafos, el tipo de datos de ruta de grafo representa una secuencia de nodos intercalados con aristas y muestra cómo se relacionan estos nodos y aristas. Para obtener más información sobre el tipo de datos de ruta, consulta Tipo de ruta de gráfico.
Con el lenguaje de gráficos de Spanner (GQL), puedes crear rutas de gráficos y realizar consultas en ellas. Los ejemplos de este documento usan el mismo esquema de Spanner Graph que se encuentra en la página Configurar y consultar Spanner Graph.
Construir una ruta de gráfico
Puede crear una ruta de gráfico creando una variable de ruta en un patrón de gráfico o con la función PATH
.
Te recomendamos que crees una ruta de gráfico mediante la variable de ruta. El formato para crear una variable de ruta es el siguiente:
MATCH p = PATH_PATTERN
Para obtener más información, consulta Gráfico de patrones.
Ejemplo
En el siguiente ejemplo, la consulta busca patrones de transferencias de dinero entre cuentas de FinGraph
.
GRAPH FinGraph
MATCH p = (src:Account {id: 16})-[t:Transfers]->{2}(dst:Account {id: 7})
RETURN TO_JSON(p) AS full_path;
Resultado
full_path |
---|
[{"identifier": ..., "properties": {"id": 16, ...}, ...}, {"identifier": ..., "properties": {"amount": 300.0, ...}, ...}, ...] |
El resultado indica que la consulta ha encontrado el patrón Account -> Transfers -> Account
en la base de datos.
Consultar una ruta de un gráfico
Puedes usar las siguientes funciones específicas de la ruta para consultar una ruta de un gráfico. Para obtener información más general sobre las consultas de Spanner Graph, consulta la descripción general de las consultas.
EDGES
La función EDGES
devuelve todos los arcos de una ruta de un grafo. Para obtener información detallada sobre la semántica, consulta EDGES
.
Ejemplo
Esta consulta busca una ruta entre dos cuentas que pasa por una cuenta intermedia.
Devuelve la cantidad del segundo borde Transfers
de la ruta, que puede estar entre src
y mid
o entre mid
y dst
.
GRAPH FinGraph
MATCH p = (src:Account {id: 7})-[t1:Transfers]->{1,3}(mid:Account)-[t2:Transfers]->
{1,3}(dst:Account {id: 16})
LET second_edge = EDGES(p)[1]
RETURN DISTINCT src.id AS src, dst.id AS dst, second_edge.amount AS second_edge_amount;
Resultado
src | dst | second_edge_amount |
---|---|---|
7 | 16 | 300 |
NODES
La función NODES
devuelve todos los nodos de una ruta de un gráfico. Para obtener información detallada sobre la semántica, consulta NODES
.
Ejemplo
Esta consulta busca la ruta del gráfico de dos transferencias y, a continuación, devuelve una lista JSON que representa la ruta.
GRAPH FinGraph
MATCH p = (src:Account)-[t:Transfers]->{2}(dst:Account)
RETURN TO_JSON(NODES(p)) AS nodes;
Resultado
nodos |
---|
[{"identifier": "...", "properties": {"id": 16}, ...}, {"identifier": "...", "properties": {"id": 20, ...}, ...] |
... |
PATH_FIRST
La función PATH_FIRST
busca el primer nodo de una ruta de gráfico. Para obtener información detallada sobre la semántica, consulta PATH_FIRST
.
Ejemplo
Esta consulta busca el primer nodo de una ruta de gráfico de dos transferencias. Devuelve la etiqueta del nodo Account
y el apodo de la cuenta.
GRAPH FinGraph
MATCH p = -[:Transfers]->{1,3}(dst:Account{id: 7})
RETURN DISTINCT PATH_FIRST(p).id AS can_reach_target;
Resultado
can_reach_target |
---|
7 |
16 |
20 |
PATH_LAST
La función PATH_LAST
busca el último nodo de una ruta de un gráfico. Para obtener información detallada sobre la semántica, consulta PATH_LAST
.
Ejemplo
Esta consulta busca el último nodo de una ruta de gráfico de dos transferencias. Devuelve la etiqueta del nodo Account
y el apodo de la cuenta.
GRAPH FinGraph
MATCH p =(start:Account{id: 7})-[:Transfers]->{1,3}
RETURN DISTINCT PATH_LAST(p).id as can_reach_target;
Resultado
can_reach_target |
---|
7 |
16 |
20 |
PATH_LENGTH
La función PATH_LENGTH
busca el número de aristas de una ruta de un gráfico. Para obtener información detallada sobre la semántica, consulta PATH_LENGTH
.
Ejemplo
Esta consulta busca el número de aristas de una ruta de gráfico que contiene entre una y tres transferencias.
GRAPH FinGraph
MATCH p = (src:Account)-[e:Transfers]->{1,3}(dst:Account)
RETURN PATH_LENGTH(p) AS num_transfers, COUNT(*) AS num_paths;
Resultado
num_transfers | num_paths |
---|---|
1 | 5 |
2 | 7 |
3 | 11 |
IS_ACYCLIC
La función IS_ACYCLIC
comprueba si una ruta de gráfico tiene nodos repetidos. Devuelve TRUE
si se encuentra una repetición; de lo contrario, devuelve FALSE
. Para obtener información detallada sobre la semántica, consulta IS_ACYCLIC
.
Ejemplo
Esta consulta comprueba si esta ruta de gráfico tiene nodos repetidos.
GRAPH FinGraph
MATCH p = (src:Account)-[t:Transfers]->{2}(dst:Account)
RETURN IS_ACYCLIC(p) AS is_acyclic_path,
ARRAY_TRANSFORM(NODES(p), n->n.id) AS account_ids;
Resultado
is_acyclic_path | account_ids |
---|---|
TRUE | 16,20,7 |
TRUE | 20.7.16 |
TRUE | 20.7.16 |
FALSO | 16,20,16 |
TRUE | 7,16,20 |
TRUE | 7,16,20 |
FALSO | 20,16,20 |
IS_TRAIL
La función IS_TRAIL
comprueba si una ruta de un grafo tiene aristas repetidas. Devuelve TRUE
si se encuentra una repetición; de lo contrario, devuelve FALSE
. Para obtener información detallada sobre la semántica, consulta IS_TRAIL
.
Ejemplo
Esta consulta comprueba si esta ruta de gráfico tiene aristas repetidas.
GRAPH FinGraph
MATCH p = (src:Account)-[t:Transfers]->{3}(dst:Account)
WHERE src.id < dst.id
RETURN IS_TRAIL(p) AS is_trail_path,
ARRAY_TRANSFORM(t, t->t.id) AS transfer_ids
Resultado
is_trail_path | transfer_ids |
---|---|
FALSO | 16,20,16 |
TRUE | 7,16,20 |
TRUE | 7,16,20 |
Modos de ruta
En Spanner Graph, el comportamiento predeterminado es devolver todas las rutas, incluidas las rutas con nodos y aristas repetidos. Puede usar los siguientes modos de ruta para incluir o excluir rutas que tengan nodos y aristas repetidos. Para obtener información detallada sobre la semántica, consulta la documentación del modo de ruta.
WALK
El modo de ruta WALK
devuelve todas las rutas, incluidas las que tienen nodos y aristas repetidos. WALK
es el modo de ruta predeterminado.
Ejemplo
La siguiente consulta muestra cómo se usa el modo de ruta WALK
en un patrón de ruta cuantificado.
El primer trayecto de los resultados tiene aristas repetidas.
GRAPH FinGraph
MATCH p = WALK (src:Account)-[t:Transfers]->{3}(dst:Account)
WHERE src.id < dst.id
RETURN ARRAY_TRANSFORM(t, t->t.id) AS transfer_ids
Resultado
transfer_ids |
---|
16,20,16 |
7,16,20 |
7,16,20 |
ACYCLIC
El modo de ruta ACYCLIC
filtra las rutas que tienen nodos repetidos.
Ejemplo
La siguiente consulta muestra cómo se usa el modo de ruta ACYCLIC
en un patrón de ruta cuantificado.
La ruta con nodos src
y dst
iguales se filtra.
GRAPH FinGraph
MATCH p = ACYCLIC (src:Account)-[t:Transfers]->{2}(dst:Account)
RETURN ARRAY_TRANSFORM(NODES(p), n->n.id) AS account_ids
Resultado
account_ids |
---|
16,20,7 |
20.7.16 |
20.7.16 |
7,16,20 |
7,16,20 |
TRAIL
El modo de ruta TRAIL
filtra las rutas que tienen bordes repetidos.
Ejemplo
La siguiente consulta muestra cómo se usa el modo de ruta TRAIL
en un patrón de ruta cuantificado.
Las rutas con aristas repetidas se filtran.
GRAPH FinGraph
MATCH p = TRAIL (src:Account)-[t:Transfers]->{3}(dst:Account)
WHERE src.id < dst.id
RETURN ARRAY_TRANSFORM(t, t->t.id) AS transfer_ids
Resultado
transfer_ids |
---|
7,16,20 |
7,16,20 |
Prefijo de búsqueda de ruta
Puede usar un prefijo de búsqueda de ruta para restringir un patrón de ruta y que devuelva la ruta más corta de cada partición de datos. Para obtener información detallada sobre la semántica, consulta Prefijo de búsqueda de ruta.
ANY SHORTEST
El prefijo de búsqueda de ruta ANY SHORTEST
devuelve la ruta más corta (la ruta con el menor número de aristas) que coincide con el patrón de cada partición de datos. Si hay más de un camino más corto por partición, devuelve cualquiera de ellos.
Ejemplo
La siguiente consulta coincide con cualquier ruta entre cada par de [a, b]
.
GRAPH FinGraph
MATCH p = ANY SHORTEST (a:Account {is_blocked:true})-[t:Transfers]->{1,4}(b:Account)
LET total_amount = SUM(t.amount)
RETURN a.id AS account1_id, total_amount, b.id AS account2_id;
Resultado
account1_id | total_amount | account2_id |
---|---|---|
16 | 500 | 16 |
16 | 800 | 7 |
16 | 300 | 20 |
Reglas de conversión
Para obtener más información, consulta las reglas de conversión de GRAPH_PATH.
Ejemplo de caso práctico
En el siguiente ejemplo de caso práctico, todas las cuentas se han enrutado a través de una a tres cuentas, desde el ID de cuenta 20
.
GRAPH FinGraph
MATCH p = (start:Account {id: 20})-[:Transfers]->{1,3}(dst:Account)
RETURN DISTINCT dst.id AS dst;
Resultado
dst |
---|
7 |
16 |
20 |
Sin embargo, una consulta que devuelva el ID de cuenta 20
podría ser demasiado genérica, ya que empieza por el ID de cuenta 20
. Para mostrar resultados más específicos, puedes
forzar tu consulta para que solo muestre rutas de gráficos acíclicos sin nodos repetidos.
Para ello, puede hacer lo siguiente:
- Usa
MATCH p = ACYCLIC <path_pattern>
. - Aplicar un filtro
IS_ACYCLIC(p)
en la consulta
La siguiente consulta usa MATCH p = ACYCLIC PATH_PATTERN
:
GRAPH FinGraph
MATCH p = ACYCLIC (start:Account {id: 20})-[:Transfers]->{1,3}(dst:Account)
RETURN DISTINCT dst.id AS dst;
Resultado
dst |
---|
7 |
16 |
Si quieres saber la primera cuenta a través de la que se transfiere el dinero, puedes ejecutar la siguiente consulta:
GRAPH FinGraph
MATCH p = ACYCLIC (start:Account {id: 20})(-[:Transfers]->
(nexts:Account)){1,3}(dst:Account)
RETURN dst.id AS dst, ARRAY_AGG(DISTINCT nexts[0].id) AS unique_starts;
Esta consulta no es habitual porque introduce una nueva variable en la ruta cuantificada mediante nexts
para obtener el resultado. Con las variables de ruta, puedes simplificar la consulta:
GRAPH FinGraph
MATCH p = ACYCLIC (start:Account {id: 20})-[:Transfers]->{1,3}(dst:Account)
RETURN dst.id AS dst, ARRAY_AGG(DISTINCT NODES(p)[OFFSET(1)].id) AS unique_starts;
Si usas NODES(p)
, se devuelven todos los nodos de la ruta. Como la primera cuenta de nodo se especifica como start
, la siguiente (en el primer desplazamiento) es la primera cuenta a través de la cual se transfiere dinero.
Resultado
dst | unique_starts |
---|---|
7 | 16, 7 |
Las rutas son más útiles cuando hay varias rutas cuantificadas. Puedes añadir una restricción para que las rutas encontradas en start
pasen por el ID de cuenta 7
:
GRAPH FinGraph
MATCH p = ACYCLIC (start:Account {id: 20})-[:Transfers]->
{1,3}(mid:Account {id: 7})-[:Transfers]->{1,3}(dst:Account)
RETURN dst.id AS dst,
ARRAY_AGG(DISTINCT NODES(p)[OFFSET(1)].id) AS unique_starts;
Aunque la instrucción MATCH
ha cambiado, el resto de la consulta no tiene por qué hacerlo. Si no se usan variables de ruta, hay casos en los que Spanner no puede saber de forma estática qué ruta cuantificada debe inspeccionar.
Si usas una variable de ruta, puedes obtener la suma de todas las transferencias:
GRAPH FinGraph
MATCH p = ACYCLIC (start:Account {id: 20})-[:Transfers]->
{1,3}(mid:Account {id: 7})-[:Transfers]->{1,3}(dst:Account)
LET all_transfers = EDGES(p)
LET transfer_amounts = SUM(all_transfers.amount)
RETURN dst.id AS dst,
ARRAY_AGG(DISTINCT NODES(p)[OFFSET(1)].id) AS participating_neighbor_nodes, transfer_amounts;
Resultado
dst | participating_neighbor_nodes | transfer_amounts |
---|---|---|
16 | 7 | 600 |
16 | 7 | 800 |