Trabalhe com caminhos

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

O que se segue?