Esta página descreve como trabalhar com caminhos de grafos no Spanner Graph.
Nas bases de dados de grafos, o tipo de dados do caminho do grafo representa uma sequência de nós intercalados com arestas e mostra como estes nós e arestas estão relacionados. Para saber mais sobre o tipo de dados de caminho, consulte o artigo Tipo de caminho do gráfico.
Com a linguagem de grafos do Spanner (GQL), pode construir caminhos de grafos e executar consultas sobre eles. Os exemplos neste documento usam o mesmo esquema do Spanner Graph que se encontra na página Configure e consulte o Spanner Graph.
Construa um caminho de gráfico
Pode construir um caminho de gráfico criando uma variável de caminho num padrão de gráfico ou
com a função PATH
.
Recomendamos que construa um caminho do gráfico através da variável de caminho. O formato para criar uma variável de caminho é:
MATCH p = PATH_PATTERN
Para mais informações, consulte o artigo Padrão de gráfico.
Exemplo
No exemplo seguinte, a consulta encontra padrões de transferências de dinheiro entre contas no domínio 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, ...}, ...}, ...] |
O resultado indica que a consulta encontrou o padrão Account -> Transfers -> Account
na base de dados.
Consultar um caminho do gráfico
Pode usar as seguintes funções específicas do caminho para consultar um caminho do gráfico. Para ver informações mais gerais sobre as consultas do Spanner Graph, consulte a vista geral das consultas.
EDGES
A função EDGES
devolve todas as arestas num caminho do gráfico. Para ver a semântica detalhada, consulte EDGES
.
Exemplo
Esta consulta encontra um caminho entre duas contas que passam por uma conta intermédia.
Devolve o valor da segunda aresta Transfers
no caminho, que pode estar entre src
e mid
ou entre mid
e 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
A função NODES
devolve todos os nós num caminho do gráfico. Para ver a semântica detalhada, consulte NODES
.
Exemplo
Esta consulta encontra o caminho do gráfico de duas transferências e, em seguida, devolve uma lista JSON que representa o caminho.
GRAPH FinGraph
MATCH p = (src:Account)-[t:Transfers]->{2}(dst:Account)
RETURN TO_JSON(NODES(p)) AS nodes;
Resultado
nós |
---|
[{"identifier": "...", "properties": {"id": 16}, ...}, {"identifier": "...", "properties": {"id": 20, ...}, ...] |
… |
PATH_FIRST
A função PATH_FIRST
encontra o primeiro nó num caminho do gráfico. Para ver a semântica detalhada, consulte PATH_FIRST
.
Exemplo
Esta consulta encontra o primeiro nó num caminho de gráfico de duas transferências. Devolve a etiqueta do nó Account
e a alcunha da conta.
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
A função PATH_LAST
encontra o último nó num caminho do gráfico. Para ver a semântica detalhada, consulte PATH_LAST
.
Exemplo
Esta consulta encontra o último nó num caminho de gráfico de duas transferências. Devolve a etiqueta do nó Account
e a alcunha da conta.
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
A função PATH_LENGTH
encontra o número de arestas num caminho do gráfico. Para ver a semântica detalhada, consulte PATH_LENGTH
.
Exemplo
Esta consulta encontra o número de arestas num caminho do gráfico que contém uma a três transferências.
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
A função IS_ACYCLIC
verifica se um caminho do gráfico tem nós repetidos. Devolve TRUE
se for encontrada uma repetição. Caso contrário, devolve FALSE
. Para ver a semântica detalhada, consulte IS_ACYCLIC
.
Exemplo
Esta consulta verifica se este caminho do gráfico tem nós 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 |
FALSE | 16,20,16 |
TRUE | 7,16,20 |
TRUE | 7,16,20 |
FALSE | 20,16,20 |
IS_TRAIL
A função IS_TRAIL
verifica se um caminho do gráfico tem arestas repetidas. Devolve TRUE
se for encontrada uma repetição. Caso contrário, devolve FALSE
. Para ver a semântica detalhada, consulte IS_TRAIL
.
Exemplo
Esta consulta verifica se este caminho do gráfico tem arestas 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 |
---|---|
FALSE | 16,20,16 |
TRUE | 7,16,20 |
TRUE | 7,16,20 |
Modos de caminho
No Spanner Graph, o comportamento predefinido é devolver todos os caminhos, incluindo caminhos com nós e arestas repetidos. Pode usar os seguintes modos de caminho para incluir ou excluir caminhos que tenham nós e arestas repetidos. Para ver a semântica detalhada, consulte a documentação do modo de caminho.
WALK
O modo de caminho WALK
devolve todos os caminhos, incluindo caminhos com nós e arestas repetidos. WALK
é o modo de caminho predefinido.
Exemplo
A consulta seguinte demonstra a utilização do modo de caminho WALK
num
padrão de caminho quantificado.
O primeiro caminho nos resultados tem arestas 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
O modo de caminho ACYCLIC
filtra os caminhos que têm nós repetidos.
Exemplo
A consulta seguinte demonstra a utilização do modo de caminho ACYCLIC
num
padrão de caminho quantificado.
O caminho com nós src
e dst
iguais é filtrado.
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
O modo de caminho TRAIL
filtra os caminhos que têm arestas repetidas.
Exemplo
A consulta seguinte demonstra a utilização do modo de caminho TRAIL
num
padrão de caminho quantificado.
Os caminhos com arestas repetidas são filtrados.
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 |
Prefixo de pesquisa de caminho
Pode usar um prefixo de pesquisa de caminho para restringir um padrão de caminho de modo a devolver o caminho mais curto de cada partição de dados. Para ver a semântica detalhada, consulte Prefixo de pesquisa de caminho.
ANY SHORTEST
O prefixo de pesquisa de caminho ANY SHORTEST
devolve o caminho mais curto (o caminho com o menor número de arestas) que corresponde ao padrão de cada partição de dados. Se existirem mais do que um caminho mais curto por partição, devolve qualquer um deles.
Exemplo
A seguinte consulta corresponde a qualquer caminho 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 |
Regras de conversão
Para mais informações, consulte o artigo Regras de conversão GRAPH_PATH.
Exemplo de utilização
No exemplo de exemplo de utilização seguinte, verifica que todas as contas foram encaminhadas
através de uma a três contas, a partir do ID da conta 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 |
No entanto, uma consulta que devolve o ID da conta 20
pode ser uma consulta demasiado abrangente, porque começa com o ID da conta 20
. Para apresentar resultados mais específicos, pode
forçar a sua consulta a apresentar apenas caminhos de grafos acíclicos sem nós repetidos.
Para o fazer, pode:
- Use
MATCH p = ACYCLIC <path_pattern>
; ou - Aplique um filtro
IS_ACYCLIC(p)
na consulta
A seguinte 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 |
Se quiser saber a primeira conta através da qual o dinheiro é transferido, pode executar a seguinte 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 não é convencional porque introduz uma nova variável no caminho quantificado através de nexts
para obter o resultado. Com as variáveis de caminho, pode simplificar a 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;
A utilização de NODES(p)
devolve todos os nós ao longo do caminho. Uma vez que a conta do nó
é especificada como start
, a seguinte (no primeiro desvio) é a primeira
conta através da qual o dinheiro é transferido.
Resultado
dst | unique_starts |
---|---|
7 | 16, 7 |
Os caminhos são mais úteis quando existem vários caminhos quantificados. Pode adicionar
uma restrição de que os caminhos encontrados a partir de start
têm de passar pelo ID da conta
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;
Embora a declaração MATCH
tenha sido alterada, não é necessário alterar o resto da consulta. Sem usar variáveis de caminho, existem casos em que não é possível
para o Spanner saber estaticamente que caminho quantificado inspecionar.
Usando uma variável de caminho, pode obter a soma de todas as transferências:
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 |