Vista geral das consultas do Spanner Graph

Este documento descreve como consultar gráficos de propriedades no Spanner Graph. Os exemplos nesta secção usam o esquema de grafos que cria em Configure e consulte o Spanner Graph, que é ilustrado no seguinte diagrama:

Exemplo de esquema do gráfico do Spanner.

Execute uma consulta do Spanner Graph

Pode executar consultas de grafos do Spanner das seguintes formas:

Visualize os resultados da consulta do Spanner Graph

Pode visualizar os resultados da consulta do Spanner Graph no Spanner Studio se a consulta devolver nós completos no formato JSON. Para mais informações, consulte Trabalhe com visualizações de gráficos do Spanner.

Estrutura de consulta do Spanner Graph

Esta secção descreve detalhadamente cada componente de consulta.

O exemplo seguinte ilustra a estrutura básica de uma consulta do Spanner Graph.

Exemplo de estrutura de consulta do Spanner Graph.

O Spanner Graph permite-lhe criar vários gráficos numa base de dados. A consulta começa por especificar o gráfico de destino, FinGraph, através da cláusula GRAPH.

Correspondência de padrões de grafos

A correspondência de padrões de grafos encontra padrões específicos no seu grafo. Os padrões mais básicos são os padrões de elementos (padrões de nós e padrões de arestas), que correspondem a elementos de grafos (nós e arestas, respetivamente). Os padrões de elementos podem ser compostos em padrões de caminhos e padrões mais complexos.

Padrões de nós

Um padrão de nó é um padrão que corresponde a nós do seu gráfico. Este padrão compreende um par de parênteses correspondente, que pode conter opcionalmente uma variável de padrão de gráfico, uma expressão de etiqueta e filtros de propriedades.

Encontre todos os nós

A seguinte consulta devolve todos os nós no gráfico. A variável n, denominada variável de padrão de gráfico, é associada aos nós correspondentes. Neste caso, o padrão de nó corresponde a todos os nós no gráfico.

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

Resultado

A consulta devolve label e id da seguinte forma:

etiqueta id
Conta 7
Conta 16
Conta 20
Pessoa 1
Pessoa 2
Pessoa 3

Encontre todos os nós com uma etiqueta específica

A seguinte consulta corresponde a todos os nós no gráfico que têm a etiqueta Person label. A consulta devolve as propriedades label e id, name dos nós com correspondência.

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

Resultado

etiqueta id nome
Pessoa 1 Alex
Pessoa 2 Dana
Pessoa 3 Lee

Encontre todos os nós que correspondem a uma expressão de etiqueta

Pode criar uma expressão de etiqueta com um ou mais operadores lógicos.

A seguinte consulta corresponde a todos os nós no gráfico que têm a etiqueta Person ou Account. O conjunto de propriedades expostas pela variável de padrão de gráfico n é o superconjunto das propriedades expostas pelos nós que têm a etiqueta Person ou Account.

GRAPH FinGraph
MATCH (n:Person|Account)
RETURN LABELS(n) AS label, n.id, n.birthday, n.create_time;
  • Nos resultados, todos os nós têm a propriedade id.
  • Os nós correspondentes à etiqueta Account têm a propriedade create_time, mas não têm a propriedade birthday. É devolvido um NULL para a propriedade birthday para esses nós.
  • Os nós correspondentes à etiqueta Person têm a propriedade birthday, mas não têm a propriedade create_time. É devolvido um NULL para a propriedade create_time para esses nós.

Resultado

etiqueta id aniversário create_time
Conta 7 NULL 2020-01-10T14:22:20.222Z
Conta 16 NULL 2020-01-28T01:55:09.206Z
Conta 20 NULL 2020-02-18T13:44:20.655Z
Pessoa 1 1991-12-21T08:00:00Z NULL
Pessoa 2 1980-10-31T08:00:00Z NULL
Pessoa 3 1986-12-07T08:00:00Z NULL

Para mais informações sobre as regras de expressão de etiquetas, consulte o artigo Expressão de etiquetas.

Encontre todos os nós que correspondem à expressão de etiqueta e ao filtro de propriedades

A seguinte consulta corresponde a todos os nós no gráfico que têm a etiqueta Person e onde a propriedade id é igual a 1.

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

Resultado

etiqueta id nome aniversário
Pessoa 1 Alex 1991-12-21T08:00:00Z

Pode usar a cláusula WHERE para formar condições de filtragem mais complexas em etiquetas e propriedades.

A seguinte consulta corresponde a todos os nós no gráfico que têm a etiqueta Person e a propriedade birthday é 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 nome aniversário
Pessoa Dana 1980-10-31T08:00:00Z
Pessoa Lee 1986-12-07T08:00:00Z

Padrões de limites

Um padrão de aresta corresponde a arestas ou relações entre nós. Os padrões de arestas estão entre parênteses retos [] com os símbolos -, -> ou <- para indicar direções.

Semelhantes aos padrões de nós, as variáveis de padrão de grafos são usadas para associar a elementos de arestas correspondentes.

Encontre todas as arestas com etiquetas correspondentes

A consulta seguinte devolve todas as arestas no gráfico que têm a etiqueta Transfers. A variável de padrão de gráfico e está associada às arestas correspondentes.

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

Encontrar todas as arestas que correspondem à expressão de etiqueta e ao filtro de propriedades

Semelhante a um padrão de nó, um padrão de aresta pode usar expressões de etiqueta, especificação de propriedade e cláusulas WHERE, como mostrado na consulta seguinte. A consulta encontra todas as arestas etiquetadas com Transfers que correspondem a um 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

Encontre todas as arestas usando qualquer padrão de arestas de direção

Embora todas as arestas no gráfico do Spanner sejam direcionadas, pode usar o any direction padrão de arestas -[]- numa consulta para corresponder a arestas em qualquer direção.

A seguinte consulta encontra todas as transferências que envolvem uma conta bloqueada.

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

Resultado

order_number valor
304330008004315 300
304120005529714 100
103650009791820 300
302290001255747 200

Padrões de caminho

Um padrão de caminho é criado a partir de padrões de nós e arestas alternados.

Encontrar todos os caminhos a partir de um nó com filtros de etiquetas e propriedades especificados, usando um padrão de caminho

A seguinte consulta encontra todas as transferências para uma conta iniciadas a partir de uma conta pertencente a Person com id igual a 2.

Cada resultado com correspondência representa um caminho de Person {id: 2} através de um Account ligado usando a aresta Owns, para outro Account usando a aresta 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

Padrões de caminhos quantificados

Um padrão quantificado permite que um padrão seja repetido dentro de um intervalo especificado.

Faça corresponder um padrão de contorno quantificado

A seguinte consulta encontra todas as contas de destino que estão a um a três transferências de distância de uma origem Account com id igual a 7, exceto a própria origem.

O padrão de limite com o quantificador {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

O exemplo anterior usa a função ARRAY_LENGTH para aceder ao group variable e. Para mais informações, consulte a variável do grupo de acesso.

Algumas linhas nos resultados de exemplo são repetidas porque podem existir vários caminhos entre o mesmo par de contas src e dst que correspondem ao padrão.

Faça corresponder um padrão de caminho quantificado

A consulta seguinte encontra caminhos entre nós Account com um a dois Transfers limites através de contas intermédias que estão bloqueadas.

O padrão do caminho entre parênteses é quantificado e a cláusula WHERE é usada nos parênteses para especificar condições para o padrão 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

Variáveis de grupo

Uma variável de padrão de gráfico declarada num padrão quantificado é considerada uma variável de grupo quando acedida fora do padrão quantificado e é associada a uma matriz de elementos do gráfico correspondentes.

Pode aceder a uma variável de grupo como uma matriz em que os elementos do gráfico são preservados pela ordem de apresentação ao longo dos caminhos correspondentes. Pode agregar uma variável de grupo usando a agregação horizontal.

Variável do grupo de acesso

No exemplo seguinte, a variável e é acedida da seguinte forma:

  • Uma variável de padrão de gráfico associada a uma única aresta na cláusula WHEREe.amount > 100 (no padrão quantificado).
  • Uma variável de grupo associada a uma matriz de elementos de aresta em ARRAY_LENGTH(e) na declaração RETURN (fora do padrão quantificado).
  • Uma variável de grupo associada a uma matriz de elementos de aresta, que é agregada por SUM(e.amount) fora do padrão quantificado. Este é um exemplo de agregação 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

Quaisquer caminhos e caminhos mais curtos

Para limitar os caminhos correspondentes em cada grupo de caminhos que partilham os mesmos nós de origem e destino, pode usar o ANY ou o ANY SHORTEST prefixo de pesquisa do caminho. Só pode aplicar estes prefixos antes de um padrão de caminho completo e não os pode aplicar entre parênteses.

Corresponda usando QUALQUER

A seguinte consulta encontra todas as contas únicas acessíveis que estão a um ou dois níveis de distância de um determinado nó Account.Transfers

O prefixo de pesquisa de caminho ANY garante que apenas é devolvido um caminho entre um par único de nós src e dst Account. No exemplo seguinte, embora possa alcançar o nó Account com {id: 16} em dois caminhos diferentes a partir do nó Account de origem, os resultados incluem apenas um caminho.

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

Padrões de gráficos

Um padrão de gráfico consiste num ou mais padrões de caminho, separados por vírgula (,). Os padrões de gráfico podem conter uma cláusula WHERE, que lhe permite aceder a todas as variáveis de padrão de gráfico nos padrões de caminho para formar condições de filtragem. Cada padrão de caminho gera uma coleção de caminhos.

Encontre correspondências através de um padrão de gráfico

A seguinte consulta identifica contas de intermediários e os respetivos proprietários envolvidos em valores de transações superiores a 200, através dos quais os fundos são transferidos de uma conta de origem para uma conta bloqueada.

Os seguintes padrões de caminho formam o padrão de gráfico:

  • O primeiro padrão encontra caminhos em que a transferência ocorre de uma conta para uma conta bloqueada através de uma conta intermédia.
  • O segundo padrão encontra caminhos de uma conta para a pessoa proprietária.

A variável interm funciona como uma ligação comum entre os dois padrões de caminho, o que requer que interm faça referência ao mesmo nó de elemento em ambos os padrões de caminho. Isto cria uma operação de junção igual com base na variável 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

Instruções de consulta lineares

Pode encadear várias declarações de grafos para formar uma declaração de consulta linear. As declarações são executadas pela mesma ordem em que aparecem na consulta.

  • Cada declaração usa o resultado da declaração anterior como entrada. A entrada está vazia para a primeira declaração.
  • O resultado da última declaração é o resultado final.

Encontre a transferência máxima para uma conta bloqueada

A seguinte consulta encontra a conta e o respetivo proprietário com a maior transferência de saída para uma conta 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;

A tabela seguinte ilustra como os resultados intermédios são transmitidos nas declarações. Apenas são apresentadas algumas propriedades dos resultados intermédios, por brevidade.

Extracto Resultado intermédio (abreviado)
MATCH
  (src_account:Account)
    -[transfer:Transfers]->
  (dst_account:Account {is_blocked:true})
src_account transferência 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ência 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ência dst_account
{id: 7} {amount: 300.0} {id: 16, is_blocked: true}

MATCH
  (src_account:Account)
    <-[owns:Owns]-
  (owner:Person)
src_account transferência dst_account é proprietário proprietário
{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

Instrução return

A instrução return define o que devolver dos padrões correspondentes. Pode aceder a variáveis de padrão de gráfico, conter expressões e outras cláusulas, como ORDER_BY e GROUP_BY. Consulte o RETURN extrato.

O Spanner Graph não suporta a devolução de elementos do gráfico como resultados da consulta. Para devolver o elemento do gráfico completo, use a função TO_JSON ou a função SAFE_TO_JSON. Destas duas funções, recomendamos que use SAFE_TO_JSON.

Devolver elementos do gráfico 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"}}

Compor consultas maiores com a palavra-chave NEXT

Pode encadear várias declarações de consulta linear de gráficos usando a palavra-chave NEXT. A entrada para a primeira declaração de consulta linear está vazia. O resultado de cada declaração de consulta linear torna-se entrada para a declaração de consulta linear seguinte.

O exemplo seguinte encontra o proprietário da conta com o maior número de transferências recebidas encadeando várias declarações lineares de gráficos. Tenha em atenção que pode usar a mesma variável, account neste exemplo, para se referir ao mesmo elemento do gráfico em várias declarações lineares.

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

Funções e expressões

Pode usar todas as funções do GoogleSQL (funções agregadas e escalares), operadores e expressões condicionais na consulta de gráficos do Spanner. O Spanner Graph também suporta funções e operadores específicos de gráficos.

Funções e operadores incorporados

As seguintes funções e operadores são usadas com frequência no GQL:

  • PROPERTY_EXISTS(n, birthday): devolve se n expõe a propriedade birthday.
  • LABELS(n): devolve as etiquetas de n, conforme definido no esquema do gráfico.
  • PROPERTY_NAMES(n): devolve os nomes das propriedades de n.
  • TO_JSON(n): devolve n no formato JSON. Para mais informações, consulte a função TO_JSON.

O predicado PROPERTY_EXISTS,a função LABELS e a função TO_JSON, bem como outras funções integradas, como ARRAY_AGG e CONCAT.

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 contas localização pessoa
falso verdadeiro Pessoa ["Vacation Fund"] Adelaide, Austrália {"identifier":"mUZpbkdyYXBoLlBlcnNvbgB4kQI=","kind":"node","labels":["Person"],"properties":{"birthday":"1991-12-21T08:00:00Z","city":"Adelaide","country":"Australia","id":1,"name":"Alex"}}

Subconsultas

Uma subconsulta é uma consulta aninhada noutra consulta. As seguintes listas regras de subconsulta do gráfico do Spanner:

  • Uma subconsulta está entre um par de chavetas {}.
  • Uma subconsulta pode começar com a cláusula GRAPH inicial para especificar o gráfico no âmbito. O gráfico especificado não tem de ser o mesmo que o usado na consulta externa.
  • Quando a cláusula GRAPH é omitida na subconsulta, ocorre o seguinte:
    • O gráfico no âmbito é inferido a partir do contexto de consulta externo mais próximo.
    • A subconsulta tem de começar por uma declaração de correspondência de padrão de grafos com o MATCH.
  • Não é possível declarar novamente uma variável de padrão de gráfico declarada fora do âmbito da subconsulta, mas pode ser referida em expressões ou funções dentro da subconsulta.

Use uma subconsulta para encontrar o número total de transferências de cada conta

A consulta seguinte ilustra a utilização da subconsulta VALUE. A subconsulta está entre chavetas {} precedidas pela palavra-chave VALUE. A consulta devolve o número total de transferências iniciadas a partir de uma conta.

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

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

Para ver uma lista das expressões de subconsulta suportadas, consulte o artigo Subconsultas do Spanner Graph.

Parâmetros de consulta

Pode consultar o Spanner Graph com parâmetros. Para mais informações, consulte a sintaxe e saiba como consultar dados com parâmetros nas bibliotecas de cliente do Spanner.

A consulta seguinte ilustra a utilização de parâmetros de consulta.

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

Consultar gráficos e tabelas em conjunto

Pode usar consultas de gráficos em conjunto com SQL para aceder a informações dos seus gráficos e tabelas numa única declaração.

GRAPH_TABLE

O operador GRAPH_TABLE recebe uma consulta de gráfico linear e devolve o respetivo resultado num formato tabular que pode ser integrado perfeitamente numa consulta SQL. Esta interoperabilidade permite-lhe enriquecer os resultados das consultas de grafos com conteúdo não gráfico e vice-versa.

Por exemplo, pode criar uma tabela CreditReports e inserir alguns relatórios de crédito, como mostrado no exemplo seguinte:

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);

Em seguida, identifique pessoas de interesse através da correspondência de padrões de grafos no GRAPH_TABLE e junte os resultados da consulta de grafos à tabela CreditReports para aceder a uma classificação 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

O que se segue?

Saiba mais sobre as práticas recomendadas para otimizar consultas.