Cómo trabajar con rutas

En esta página, se describe cómo trabajar con las instrucciones de gráfico en Spanner Graph.

En las bases de datos de gráficos, el tipo de datos de ruta de gráfico 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 Spanner Graph (GQL), puedes crear rutas de acceso 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 Configura y consulta Spanner Graph.

Cómo construir una ruta de gráfico

Para construir una ruta de gráfico, crea una variable de ruta en un patrón de gráfico o con la función PATH.

Recomendamos que construyas una ruta de gráfico con 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 Patrón de gráfico.

Ejemplo

En el siguiente ejemplo, la consulta encuentra patrones de transferencias de dinero entre cuentas dentro de FinGraph.

GRAPH FinGraph
MATCH p = (src:Account {id: 16})-[t1:Transfers]->(mid:Account)-[t2:Transfers]->
  (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 encontró el patrón Account -> Transfers -> Account en la base de datos.

Cómo consultar una ruta de gráfico

Puedes usar las siguientes funciones específicas de la ruta para consultar una ruta de gráfico. Para obtener información más general sobre las consultas de Spanner Graph, consulta Descripción general de las consultas.

EDGES

La función EDGES muestra todos los bordes de una ruta de gráfico. Para obtener semántica detallada, consulta EDGES.

Ejemplo

Esta consulta encuentra una ruta entre dos cuentas que pasa por una cuenta intermedia. Muestra la cantidad del segundo borde Transfers en 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 muestra todos los nodos de una ruta de acceso de grafo. Para obtener semántica detallada, consulta NODES.

Ejemplo

Esta consulta encuentra la ruta del gráfico de dos transferencias y, luego, muestra una lista JSON que representa la ruta.

GRAPH FinGraph
MATCH p = (src:Account)-[t1:Transfers]->(mid:Account)-[t2:Transfers]->(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 encuentra el primer nodo en una ruta de acceso de gráfico. Para obtener semántica detallada, consulta PATH_FIRST.

Ejemplo

Esta consulta encuentra el primer nodo en una ruta de gráfico de dos transferencias. Devuelve la etiqueta del nodo Account y el sobrenombre 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 encuentra el último nodo en una ruta de gráfico. Para obtener semántica detallada, consulta PATH_LAST.

Ejemplo

Esta consulta encuentra el último nodo en una ruta de gráfico de dos transferencias. Muestra la etiqueta del nodo Account y el sobrenombre 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 encuentra la cantidad de aristas en una ruta de gráfico. Para obtener semántica detallada, consulta PATH_LENGTH.

Ejemplo

Esta consulta encuentra la cantidad de aristas en una ruta de gráfico que contiene de una a 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 verifica si una ruta de gráfico tiene nodos repetidos. Muestra TRUE si se encuentra una repetición; de lo contrario, muestra FALSE. Para obtener semántica detallada, consulta IS_ACYCLIC.

Ejemplo

Esta consulta verifica si esta ruta de acceso del gráfico tiene nodos repetidos.

GRAPH FinGraph
MATCH p = (src:Account)-[t1:Transfers]->(mid:Account)-[t2:Transfers]->(dst:Account)
RETURN IS_ACYCLIC(p) AS is_acyclic_path, src.id AS source_account_id,
  mid.id AS mid_account_id, dst.id AS dst_account_id;

Resultado

is_acyclic_path source_account_id mid_account_id dst_account_id
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 verifica si una ruta de gráfico tiene bordes repetidos. Muestra TRUE si se encuentra una repetición; de lo contrario, muestra FALSE. Para obtener semántica detallada, consulta IS_TRAIL.

Ejemplo

Esta consulta verifica si esta ruta de acceso del gráfico tiene aristas repetidas.

GRAPH FinGraph
MATCH p = (src:Account)-[t1:Transfers]->(mid1:Account)-[t2:Transfers]->
  (mid2:Account)-[t3:Transfers]->(dst:Account)
WHERE src.id < dst.id
RETURN IS_TRAIL(p) AS is_trail_path, t1.id AS t1_id, t2.id AS t2_id, t3.id AS t3_id;

Resultado

is_trail_path t1_id t2_id t3_id
FALSO 16 20 16
TRUE 7 16 20
TRUE 7 16 20

Modos de ruta de acceso

En Spanner Graph, el comportamiento predeterminado es mostrar todas las rutas, incluso las que tienen nodos y aristas repetidos. Puedes usar los siguientes modos de ruta para incluir o excluir rutas que tengan nodos y aristas repetidos. Para obtener una semántica detallada, consulta la documentación de Pathmode.

WALK

El modo de ruta WALK muestra todas las rutas, incluidas las que tienen nodos y bordes repetidos. WALK es el modo de ruta predeterminado.

Ejemplo

En la siguiente consulta, se muestra el uso del modo de ruta WALK en un patrón de ruta no cuantificado. La primera ruta de los resultados usa el mismo borde para t1 y t3.

GRAPH FinGraph
MATCH p = WALK (src:Account)-[t1:Transfers]->(mid1:Account)-[t2:Transfers]->
  (mid2:Account)-[t3:Transfers]->(dst:Account)
WHERE src.id < dst.id
RETURN t1.id AS transfer1_id, t2.id AS transfer2_id, t3.id AS transfer3_id;

Resultado

transfer1_id transfer2_id transfer3_id
16 20 16
7 16 20
7 16 20

ACYCLIC

El modo de ruta ACYCLIC filtra las rutas que tienen nodos repetidos.

Ejemplo

En la siguiente consulta, se muestra el uso del modo de ruta ACYCLIC en un patrón de ruta no cuantificado. Se filtra la ruta con nodos src y dst iguales.

GRAPH FinGraph
MATCH p = ACYCLIC (src:Account)-[t1:Transfers]->(mid:Account)-[t2:Transfers]->(dst:Account)
RETURN src.id AS account1_id, mid.id AS account2_id, dst.id AS account3_id;

Resultado

account1_id account2_id account3_id
20 7 16
20 7 16
7 16 20
7 16 20
16 20 7

TRAIL

El modo de ruta TRAIL filtra las rutas que tienen bordes repetidos.

Ejemplo

En la siguiente consulta, se muestra el uso del modo de ruta TRAIL en un patrón de ruta no cuantificado. Se filtra la ruta cuyas aristas t1 y t3 son iguales.

GRAPH FinGraph
MATCH p = TRAIL (src:Account)-[t1:Transfers]->(mid1:Account)-[t2:Transfers]->
  (mid2:Account)-[t3:Transfers]->(dst:Account)
RETURN
  t1.id AS transfer1_id, t2.id AS transfer2_id, t3.id AS transfer3_id;

Resultado

transfer1_id transfer2_id transfer3_id
16 20 7
16 20 7
20 7 16
20 7 16
7 16 20
7 16 20
7 16 20
7 16 20
20 16 20

Prefijo de búsqueda de ruta

Puedes usar un prefijo de búsqueda de ruta para restringir un patrón de ruta de acceso para que muestre la ruta más corta de cada partición de datos. Para obtener semántica detallada, consulta Prefijo de búsqueda de ruta.

ANY SHORTEST

El prefijo de búsqueda de ruta ANY SHORTEST muestra la ruta más corta (la ruta con la menor cantidad de aristas) que coincide con el patrón de cada partición de datos. Si hay más de una ruta más corta por partición, muestra cualquiera de ellas.

Ejemplo

La siguiente consulta coincide con cualquier ruta entre cada par de [a, b].

GRAPH FinGraph
MATCH p = ANY SHORTEST (a:Account)-[t:Transfers]->{1,4}(b:Account)
WHERE a.is_blocked
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 de uso

En el siguiente ejemplo de caso de uso, verás que todas las cuentas se enrutaron 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 devuelve el ID de cuenta 20 podría ser demasiado amplia porque comienza con el ID de cuenta 20. Para mostrar resultados más específicos, puedes forzar tu consulta para que muestre solo rutas de grafos acíclicos sin nodos repetidos. Para ello, puedes hacer lo siguiente:

  • Usa MATCH p = ACYCLIC <path_pattern>.
  • Aplica un filtro IS_ACYCLIC(p) en tu consulta

En la siguiente consulta, se 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 conocer la primera cuenta a través de la cual 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 convencional porque introduce una variable nueva dentro de la ruta cuantificada con 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;

El uso de NODES(p) muestra todos los nodos a lo largo de la ruta. Como la primera cuenta de nodos se especifica como start, la siguiente (en el primer desplazamiento) es la primera cuenta a través de la que se transfiere el dinero.

Resultado

DST unique_starts
7 16, 7

Las rutas son más útiles cuando hay varias rutas cuantificadas. Puedes agregar una restricción que indique que las rutas encontradas desde start deben pasar por el ID de la 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 cambió la sentencia MATCH, no es necesario que cambie el resto de la consulta. Sin usar variables de ruta, hay casos en los que no es posible que Spanner sepa de forma estática qué ruta cuantificada inspeccionar.

Con 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

¿Qué sigue?