Información general sobre las consultas de Spanner Graph

En este documento se describe cómo consultar gráficos de propiedades en Spanner Graph. En los ejemplos de esta sección se usa el esquema de gráfico que se crea en Configurar y consultar Spanner Graph, que se ilustra en el siguiente diagrama:

Ejemplo de esquema de Spanner Graph.

Ejecutar una consulta de Spanner Graph

Puedes ejecutar consultas de gráficos de Spanner de las siguientes formas:

Visualizar los resultados de las consultas de Spanner Graph

Puedes visualizar los resultados de tus consultas de gráficos de Spanner en Spanner Studio si la consulta devuelve nodos completos en formato JSON. Para obtener más información, consulta Trabajar con visualizaciones de gráficos de Spanner.

Estructura de consulta de Spanner Graph

En esta sección se describe cada componente de la consulta en detalle.

En el siguiente ejemplo se muestra la estructura básica de una consulta de gráfico de Spanner.

Ejemplo de estructura de consulta de Spanner Graph.

Spanner Graph te permite crear varios gráficos en una base de datos. La consulta empieza especificando el gráfico de destino, FinGraph, mediante la cláusula GRAPH.

Coincidencia de patrones de grafos

La coincidencia de patrones de gráficos busca patrones específicos en tu gráfico. Los patrones más básicos son los patrones de elementos (patrones de nodos y patrones de aristas), que coinciden con los elementos de un grafo (nodos y aristas, respectivamente). Los patrones de elementos se pueden componer en patrones de ruta y patrones más complejos.

Patrones de nodos

Un patrón de nodo es un patrón que coincide con los nodos de tu gráfico. Este patrón incluye un par de paréntesis que coinciden y que pueden contener una variable de patrón de gráfico, una expresión de etiqueta y filtros de propiedades.

Buscar todos los nodos

La siguiente consulta devuelve todos los nodos del gráfico. La variable n, denominada variable de patrón de gráfico, se vincula a los nodos coincidentes. En este caso, el patrón de nodo coincide con todos los nodos del gráfico.

GRAPH FinGraph
MATCH (n)
RETURN LABELS(n) AS label, n.id;

Resultado

La consulta devuelve label y id de la siguiente manera:

etiqueta id
Cuenta 7
Cuenta 16
Cuenta 20
Persona 1
Persona 2
Persona 3

Buscar todos los nodos con una etiqueta específica

La siguiente consulta coincide con todos los nodos del gráfico que tienen la etiqueta Person . La consulta devuelve las propiedades label y id, name de los nodos coincidentes.

GRAPH FinGraph
MATCH (p:Person)
RETURN LABELS(p) AS label, p.id, p.name;

Resultado

etiqueta id name
Persona 1 Alex
Persona 2 Dana
Persona 3 Lee

Buscar todos los nodos que coincidan con una expresión de etiqueta

Puedes crear una expresión de etiqueta con uno o varios operadores lógicos.

La siguiente consulta coincide con todos los nodos del gráfico que tienen la etiqueta Person o Account. El conjunto de propiedades expuestas por la variable de patrón de grafo n es el superconjunto de las propiedades expuestas por los nodos que tienen la etiqueta Person o Account.

GRAPH FinGraph
MATCH (n:Person|Account)
RETURN LABELS(n) AS label, n.id, n.birthday, n.create_time;
  • En los resultados, todos los nodos tienen la propiedad id.
  • Los nodos que coinciden con la etiqueta Account tienen la propiedad create_time, pero no la propiedad birthday. Se devuelve un NULL para la propiedad birthday de estos nodos.
  • Los nodos que coinciden con la etiqueta Person tienen la propiedad birthday, pero no la propiedad create_time. Se devuelve un NULL para la propiedad create_time de estos nodos.

Resultado

etiqueta id cumpleaños create_time
Cuenta 7 NULL 2020-01-10T14:22:20.222Z
Cuenta 16 NULL 2020-01-28T01:55:09.206Z
Cuenta 20 NULL 2020-02-18T13:44:20.655Z
Persona 1 1991-12-21T08:00:00Z NULL
Persona 2 1980-10-31T08:00:00Z NULL
Persona 3 1986-12-07T08:00:00Z NULL

Para obtener más información sobre las reglas de expresiones de etiquetas, consulta Expresión de etiqueta.

Buscar todos los nodos que coincidan con la expresión de etiqueta y el filtro de propiedad

La siguiente consulta coincide con todos los nodos del gráfico que tienen la etiqueta Person y donde la propiedad id es igual a 1.

GRAPH FinGraph
MATCH (p:Person {id: 1})
RETURN LABELS(p) AS label, p.id, p.name, p.birthday;

Resultado

etiqueta id name cumpleaños
Persona 1 Alex 1991-12-21T08:00:00Z

Puedes usar la cláusula WHERE para crear condiciones de filtrado más complejas en etiquetas y propiedades.

La siguiente consulta coincide con todos los nodos del gráfico que tienen la etiqueta Person y la propiedad birthday es anterior a 1990-01-10.

GRAPH FinGraph
MATCH (p:Person WHERE p.birthday < '1990-01-10')
RETURN LABELS(p) AS label, p.name, p.birthday;

Resultado

etiqueta name cumpleaños
Persona Dana 1980-10-31T08:00:00Z
Persona Lee 1986-12-07T08:00:00Z

Patrones de borde

Un patrón de arista coincide con las aristas o las relaciones entre nodos. Los patrones de borde se incluyen entre corchetes [] con los símbolos -, -> o <- para indicar las direcciones.

Al igual que las variables de patrón de nodo, las variables de patrón de gráfico se usan para enlazar elementos de arista coincidentes.

Buscar todos los bordes con etiquetas coincidentes

La siguiente consulta devuelve todas las aristas del gráfico que tienen la etiqueta Transfers. La variable de patrón de gráfico e está vinculada a las aristas coincidentes.

GRAPH FinGraph
MATCH -[e:Transfers]->
RETURN e.Id as src_account, e.order_number

Resultado

src_account order_number
7 304330008004315
7 304120005529714
16 103650009791820
20 304120005529714
20 302290001255747

Busca todos los bordes que coincidan con la expresión de etiqueta y el filtro de propiedad.

Al igual que un patrón de nodo, un patrón de arista puede usar expresiones de etiqueta, especificaciones de propiedad y cláusulas WHERE, como se muestra en la siguiente consulta. La consulta busca todas las aristas etiquetadas con Transfers que coincidan con un order_number especificado.

GRAPH FinGraph
MATCH -[e:Transfers {order_number: "304120005529714"}]->
RETURN e.Id AS src_account, e.order_number

Resultado

src_account order_number
7 304120005529714
20 304120005529714

Encontrar todos los bordes usando cualquier patrón de borde de dirección

Aunque todas las aristas de Spanner Graph están dirigidas, puedes usar el patrón de arista any direction -[]- en una consulta para que coincida con las aristas en cualquier dirección.

La siguiente consulta busca todas las transferencias en las que participa una cuenta bloqueada.

GRAPH FinGraph
MATCH (account:Account)-[transfer:Transfers]-(:Account {is_blocked:true})
RETURN transfer.order_number, transfer.amount;

Resultado

order_number amount
304330008004315 300
304120005529714 100
103650009791820 300
302290001255747 200

Patrones de ruta

Un patrón de ruta se crea a partir de patrones de nodos y aristas alternos.

Buscar todas las rutas de un nodo con filtros de etiquetas y propiedades especificados mediante un patrón de ruta

La siguiente consulta busca todas las transferencias a una cuenta iniciadas desde una cuenta propiedad de Person con id igual a 2.

Cada resultado coincidente representa una ruta de Person {id: 2} a través de un Account conectado mediante la arista Owns a otro Account mediante la arista Transfers.

GRAPH FinGraph
MATCH
  (p:Person {id: 2})-[:Owns]->(account:Account)-[t:Transfers]->
  (to_account:Account)
RETURN
  p.id AS sender_id, account.id AS from_id, to_account.id AS to_id;

Resultado

sender_id from_id to_id
2 20 7
2 20 16

Patrones de ruta cuantificados

Un patrón cuantificado permite que un patrón se repita dentro de un intervalo especificado.

Coincidir con un patrón de arista cuantificado

La siguiente consulta busca todas las cuentas de destino que estén a una, dos o tres transferencias de un origen Account con id igual a 7, excepto la propia cuenta de origen.

El patrón de borde seguido del cuantificador {1, 3}.

GRAPH FinGraph
MATCH (src:Account {id: 7})-[e:Transfers]->{1, 3}(dst:Account)
WHERE src != dst
RETURN src.id AS src_account_id, ARRAY_LENGTH(e) AS path_length, dst.id AS dst_account_id;

Resultado

src_account_id path_length dst_account_id
7 1 16
7 1 16
7 1 16
7 3 16
7 3 16
7 2 20
7 2 20

En el ejemplo anterior se usa la función ARRAY_LENGTH para acceder a group variable e. Para obtener más información, consulta variable de grupo de acceso.

Algunas filas de los resultados de ejemplo se repiten porque puede haber varias rutas entre el mismo par de cuentas src y dst que coincidan con el patrón.

Coincidencia con un patrón de ruta cuantificado

La siguiente consulta busca rutas entre nodos Account con entre uno y dos bordes Transfers a través de cuentas intermedias bloqueadas.

El patrón de ruta entre paréntesis se cuantifica y la cláusula WHERE se usa entre paréntesis para especificar las condiciones del patrón repetido.

GRAPH FinGraph
MATCH
  (src:Account)
  ((a:Account)-[:Transfers]->(b:Account {is_blocked:true}) WHERE a != b){1,2}
    -[:Transfers]->(dst:Account)
RETURN src.id AS src_account_id, dst.id AS dst_account_id;

Resultado

src_account_id dst_account_id
7 20
7 20
20 20

Variables de grupo

Una variable de patrón de gráfico declarada en un patrón cuantificado se considera una variable de grupo cuando se accede a ella fuera del patrón cuantificado y se vincula a una matriz de elementos de gráfico coincidentes.

Puedes acceder a una variable de grupo como una matriz en la que los elementos del gráfico se conservan en el orden de aparición a lo largo de las rutas coincidentes. Puedes agregar una variable de grupo mediante la agregación horizontal.

Variable de grupo de acceso

En el siguiente ejemplo, se accede a la variable e de la siguiente manera:

  • Una variable de patrón de gráfico enlazada a un solo borde en la cláusula WHERE e.amount > 100 (dentro del patrón cuantificado).
  • Una variable de grupo vinculada a una matriz de elementos de borde en ARRAY_LENGTH(e) en la instrucción RETURN (fuera del patrón cuantificado).
  • Variable de grupo vinculada a una matriz de elementos de borde, que se agrega mediante SUM(e.amount) fuera del patrón cuantificado. Este es un ejemplo de agregación horizontal.
GRAPH FinGraph
MATCH
  (src:Account {id: 7})-[e:Transfers WHERE e.amount > 100]->{0,2}
  (dst:Account)
WHERE src.id != dst.id
LET total_amount = SUM(e.amount)
RETURN
  src.id AS src_account_id, ARRAY_LENGTH(e) AS path_length,
  total_amount, dst.id AS dst_account_id;

Resultado

src_account_id path_length total_amount dst_account_id
7 1 300 16
7 2 600 20

Cualquier ruta y ruta más corta

Para limitar las rutas coincidentes de cada grupo de rutas que compartan los mismos nodos de origen y destino, puede usar el prefijo de búsqueda de rutas ANY o ANY SHORTEST. Solo puedes aplicar estos prefijos antes de un patrón de ruta completo y no puedes aplicarlos dentro de paréntesis.

Coincide con CUALQUIER

La siguiente consulta busca todas las cuentas únicas a las que se puede acceder que estén a uno o dos Transfers de un nodo Account determinado.

El prefijo de búsqueda de ruta ANY asegura que solo se devuelva una ruta entre un par único de nodos src y dst Account. En el siguiente ejemplo, aunque puedes llegar al nodo Account con {id: 16} por dos rutas diferentes desde el nodo de origen Account, los resultados solo incluyen una ruta.

GRAPH FinGraph
MATCH ANY (src:Account {id: 7})-[e:Transfers]->{1,2}(dst:Account)
LET ids_in_path = ARRAY_CONCAT(ARRAY_AGG(e.Id), [dst.Id])
RETURN src.id AS src_account_id, dst.id AS dst_account_id, ids_in_path;

Resultado

src_account_id dst_account_id ids_in_path
7 16 7,16
7 20 7,16,20

Patrones de gráficos

Un patrón de grafo consta de uno o varios patrones de ruta separados por comas (,). Los patrones de grafo pueden contener una cláusula WHERE, que te permite acceder a todas las variables de patrón de grafo de los patrones de ruta para formar condiciones de filtrado. Cada patrón de ruta genera una colección de rutas.

Buscar coincidencias con un patrón de gráfico

La siguiente consulta identifica las cuentas intermediarias y sus propietarios implicados en transacciones con importes superiores a 200, a través de las cuales se transfieren fondos de una cuenta de origen a una cuenta bloqueada.

Los siguientes patrones de ruta forman el patrón de gráfico:

  • El primer patrón busca rutas en las que la transferencia se produce de una cuenta a una cuenta bloqueada mediante una cuenta intermedia.
  • El segundo patrón busca rutas de una cuenta a su propietario.

La variable interm actúa como un enlace común entre los dos patrones de ruta, por lo que interm debe hacer referencia al mismo nodo de elemento en ambos patrones de ruta. De esta forma, se crea una operación de unión equitativa basada en la variable interm.

GRAPH FinGraph
MATCH
  (src:Account)-[t1:Transfers]->(interm:Account)-[t2:Transfers]->(dst:Account),
  (interm)<-[:Owns]-(p:Person)
WHERE dst.is_blocked = TRUE AND t1.amount > 200 AND t2.amount > 200
RETURN
  src.id AS src_account_id, dst.id AS dst_account_id,
  interm.id AS interm_account_id, p.id AS owner_id;

Resultado

src_account_id dst_account_id interm_account_id owner_id
20 16 7 1

Declaraciones de consulta lineales

Puedes encadenar varias instrucciones de gráfico para formar una instrucción de consulta lineal. Las instrucciones se ejecutan en el mismo orden en el que aparecen en la consulta.

  • Cada instrucción toma como entrada la salida de la instrucción anterior. La entrada está vacía en la primera instrucción.
  • La salida de la última instrucción es el resultado final.

Consultar la transferencia máxima a una cuenta bloqueada

La siguiente consulta busca la cuenta y su propietario con la mayor transferencia saliente a una cuenta bloqueada.

GRAPH FinGraph
MATCH (src_account:Account)-[transfer:Transfers]->(dst_account:Account {is_blocked:true})
ORDER BY transfer.amount DESC
LIMIT 1
MATCH (src_account:Account)<-[owns:Owns]-(owner:Person)
RETURN src_account.id AS account_id, owner.name AS owner_name;

En la siguiente tabla se muestra cómo se transfieren los resultados intermedios a lo largo de las instrucciones. Solo se muestran algunas propiedades de los resultados intermedios para que sea más breve.

Declaraciones Resultado intermedio (abreviado)
MATCH
  (src_account:Account)
    -[transfer:Transfers]->
  (dst_account:Account {is_blocked:true})
src_account transfer dst_account
{id: 7} {amount: 300.0} {id: 16, is_blocked: true}
{id: 7} {amount: 100.0} {id: 16, is_blocked: true}
{id: 20} {amount: 200.0} {id: 16, is_blocked: true}

ORDER BY transfer.amount DESC
src_account transfer dst_account
{id: 7} {amount: 300.0} {id: 16, is_blocked: true}
{id: 20} {amount: 200.0} {id: 16, is_blocked: true}
{id: 7} {amount: 100.0} {id: 16, is_blocked: true}

LIMIT 1
src_account transfer dst_account
{id: 7} {amount: 300.0} {id: 16, is_blocked: true}

MATCH
  (src_account:Account)
    <-[owns:Owns]-
  (owner:Person)
src_account transfer dst_account es propietario de propietario
{id: 7} {amount: 300.0} {id: 16, is_blocked: true} {person_id: 1, account_id: 7} {id: 1, name: Alex}

RETURN
  src_account.id AS account_id,
  owner.name AS owner_name
account_id owner_name
7 Alex

Resultado

account_id owner_name
7 Alex

Instrucción de retorno

La instrucción Return define qué se debe devolver de los patrones coincidentes. Puede acceder a variables de patrones de grafos, contener expresiones y otras cláusulas como ORDER_BY y GROUP_BY. Consulta la RETURNdeclaración.

Spanner Graph no admite la devolución de elementos de gráficos como resultados de consultas. Para devolver todo el elemento del gráfico, usa la función TO_JSON o la función SAFE_TO_JSON. De estas dos funciones, te recomendamos que uses SAFE_TO_JSON.

Devolver elementos de gráficos como JSON

GRAPH FinGraph
MATCH (n:Account {id: 7})
-- Returning a graph element in the final results is NOT allowed. Instead, use
-- the TO_JSON function or explicitly return the graph element's properties.
RETURN TO_JSON(n) AS n;
GRAPH FinGraph
MATCH (n:Account {id: 7})
-- Certain fields in the graph elements, such as TOKENLIST, can't be returned
-- in the TO_JSON function. In those cases, use the SAFE_TO_JSON function instead.
RETURN SAFE_TO_JSON(n) AS n;

Resultado

n
{"identifier":"mUZpbkdyYXBoLkFjY291bnQAeJEO","kind":"node","labels":["Account"],"properties":{"create_time":"2020-01-10T14:22:20.222Z","id":7,"is_blocked":false,"nick_name":"Vacation Fund"}}

Escribir consultas más largas con la palabra clave NEXT

Puedes encadenar varias instrucciones de consulta lineal de gráficos mediante la palabra clave NEXT. La entrada de la primera instrucción de consulta lineal está vacía. El resultado de cada instrucción de consulta lineal se convierte en la entrada de la siguiente instrucción de consulta lineal.

En el siguiente ejemplo se busca el propietario de la cuenta con más transferencias entrantes encadenando varias instrucciones lineales de gráficos. Ten en cuenta que puedes usar la misma variable, account en este ejemplo, para hacer referencia al mismo elemento de gráfico en varias instrucciones lineales.

GRAPH FinGraph
MATCH (:Account)-[:Transfers]->(account:Account)
RETURN account, COUNT(*) AS num_incoming_transfers
GROUP BY account
ORDER BY num_incoming_transfers DESC
LIMIT 1

NEXT

MATCH (account:Account)<-[:Owns]-(owner:Person)
RETURN account.id AS account_id, owner.name AS owner_name, num_incoming_transfers;

Resultado

account_id owner_name num_incoming_transfers
16 Lee 3

Funciones y expresiones

Puedes usar todas las funciones de GoogleSQL (tanto las de agregación como las escalares), los operadores y las expresiones condicionales en las consultas de gráficos de Spanner. Spanner Graph también admite funciones y operadores específicos de gráficos.

Funciones y operadores integrados

Las siguientes funciones y operadores se suelen usar en GQL:

  • PROPERTY_EXISTS(n, birthday): devuelve si n expone la propiedad birthday.
  • LABELS(n): devuelve las etiquetas de n tal como se definen en el esquema del gráfico.
  • PROPERTY_NAMES(n): devuelve los nombres de las propiedades de n.
  • TO_JSON(n): devuelve n en formato JSON. Para obtener más información, consulta la función TO_JSON.

el predicado PROPERTY_EXISTS,LABELS la función TO_JSON y la función ARRAY_AGG, así como otras funciones integradas, como CONCAT y.

GRAPH FinGraph
MATCH (person:Person)-[:Owns]->(account:Account)
RETURN person, ARRAY_AGG(account.nick_name) AS accounts
GROUP BY person

NEXT

RETURN
  LABELS(person) AS labels,
  TO_JSON(person) AS person,
  accounts,
  CONCAT(person.city, ", ", person.country) AS location,
  PROPERTY_EXISTS(person, is_blocked) AS is_blocked_property_exists,
  PROPERTY_EXISTS(person, name) AS name_property_exists
LIMIT 1;

Resultado

is_blocked_property_exists name_property_exists etiquetas cuentas ubicación persona
falso true Persona ["Fondo para vacaciones"] Adelaida (Australia) {"identifier":"mUZpbkdyYXBoLlBlcnNvbgB4kQI=","kind":"node","labels":["Person"],"properties":{"birthday":"1991-12-21T08:00:00Z","city":"Adelaide","country":"Australia","id":1,"name":"Alex"}}

Subconsultas

Una subconsulta es una consulta anidada en otra consulta. A continuación, se enumeran las reglas de las subconsultas de Spanner Graph:

  • Una subconsulta se incluye entre un par de llaves {}.
  • Una subconsulta puede empezar con la cláusula GRAPH inicial para especificar el gráfico en el ámbito. El gráfico especificado no tiene por qué ser el mismo que el que se usa en la consulta externa.
  • Cuando se omite la cláusula GRAPH en la subconsulta, ocurre lo siguiente:
    • El gráfico del ámbito se deduce del contexto de consulta externo más cercano.
    • La subconsulta debe empezar por una instrucción de coincidencia de patrón de grafo con MATCH.
  • Una variable de patrón de gráfico declarada fuera del ámbito de la subconsulta no se puede volver a declarar dentro de la subconsulta, pero se puede hacer referencia a ella en expresiones o funciones dentro de la subconsulta.

Usar una subconsulta para obtener el número total de transferencias de cada cuenta

La siguiente consulta muestra el uso de la subconsulta VALUE. La subconsulta se incluye entre llaves {} precedidas por la palabra clave VALUE. La consulta devuelve el número total de transferencias iniciadas desde una cuenta.

GRAPH FinGraph
MATCH (p:Person)-[:Owns]->(account:Account)
RETURN p.name, account.id AS account_id, VALUE {
  MATCH (a:Account)-[transfer:Transfers]->(:Account)
  WHERE a = account
  RETURN COUNT(transfer) AS num_transfers
} AS num_transfers;

Resultado

name account_id num_transfers
Alex 7 2
Dana 20 2
Lee 16 1

Para ver una lista de las expresiones de subconsulta admitidas, consulta Subconsultas de gráficos de Spanner.

Los parámetros de consulta

Puedes consultar Spanner Graph con parámetros. Para obtener más información, consulta la sintaxis y aprende a consultar datos con parámetros en las bibliotecas de cliente de Spanner.

La siguiente consulta muestra el uso de los parámetros de consulta.

GRAPH FinGraph
MATCH (person:Person {id: @id})
RETURN person.name;

Consultar gráficos y tablas a la vez

Puedes usar consultas de gráficos junto con SQL para acceder a la información de tus gráficos y tablas en una sola instrucción.

GRAPH_TABLE

El operador GRAPH_TABLE toma una consulta de gráfico lineal y devuelve su resultado en formato tabular, que se puede integrar fácilmente en una consulta de SQL. Esta interoperabilidad te permite enriquecer los resultados de las consultas de gráficos con contenido que no sea de gráficos y viceversa.

Por ejemplo, puedes crear una tabla CreditReports e insertar algunos informes de crédito, como se muestra en el siguiente ejemplo:

CREATE TABLE CreditReports (
  person_id     INT64 NOT NULL,
  create_time   TIMESTAMP NOT NULL,
  score         INT64 NOT NULL,
) PRIMARY KEY (person_id, create_time);
INSERT INTO CreditReports (person_id, create_time, score)
VALUES
  (1,"2020-01-10 06:22:20.222", 700),
  (2,"2020-02-10 06:22:20.222", 800),
  (3,"2020-03-10 06:22:20.222", 750);

A continuación, identifica a las personas de interés mediante la coincidencia de patrones de gráficos en GRAPH_TABLE y combina los resultados de la consulta de gráficos con la tabla CreditReports para acceder a una puntuación de crédito.

SELECT
  gt.person.id,
  credit.score AS latest_credit_score
FROM GRAPH_TABLE(
  FinGraph
  MATCH (person:Person)-[:Owns]->(:Account)-[:Transfers]->(account:Account {is_blocked:true})
  RETURN DISTINCT person
) AS gt
JOIN CreditReports AS credit
  ON gt.person.id = credit.person_id
ORDER BY credit.create_time;

Resultado:

person_id latest_credit_score
1 700
2 800

Siguientes pasos

Consulta las prácticas recomendadas para optimizar las consultas.