Nesta página, descrevemos como trabalhar com caminhos de gráficos no Spanner Graph.
Em bancos de dados de gráficos, o tipo de dados de caminho do gráfico representa uma sequência de nós intercalados com arestas e mostra como esses nós e arestas estão relacionados. Para saber mais sobre o tipo de dados de caminho, consulte Tipo de caminho do gráfico.
Com a linguagem do Spanner Graph (GQL), é possível construir caminhos de gráficos e realizar consultas neles. Os exemplos neste documento usam o mesmo esquema do Spanner Graph encontrado na página Configurar e consultar o Spanner Graph.
Construir um caminho de gráfico
É possível criar um caminho de gráfico criando uma variável de caminho em um padrão de gráfico ou
com a função PATH.
Recomendamos construir um caminho de gráfico usando a variável de caminho. O formato para criar uma variável de caminho é:
MATCH p = PATH_PATTERN
Para mais informações, consulte Padrão de gráfico.
Exemplo
No exemplo a seguir, a consulta encontra padrões de transferências de dinheiro entre contas em 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
no banco de dados.
Consultar um caminho de gráfico
É possível usar as seguintes funções específicas de caminho para consultar um caminho de gráfico. Para mais informações gerais sobre consultas do Spanner Graph, consulte Visão geral das consultas.
EDGES
A função EDGES retorna todas as arestas em um caminho de gráfico. Para ver a semântica detalhada, consulte EDGES.
Exemplo
Essa consulta encontra um caminho entre duas contas que passam por uma conta intermediária.
Ele retorna a quantidade da segunda borda 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 retorna todos os nós em um caminho de gráfico. Para ver a semântica detalhada, consulte NODES.
Exemplo
Essa consulta encontra o caminho do gráfico de duas transferências e retorna 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ó em um caminho de gráfico. Para ver a semântica detalhada, consulte PATH_FIRST.
Exemplo
Essa consulta encontra o primeiro nó em um caminho de gráfico de duas transferências. Ele retorna o rótulo do nó Account e o apelido 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ó em um caminho de gráfico. Para ver a semântica detalhada, consulte PATH_LAST.
Exemplo
Essa consulta encontra o último nó em um caminho de gráfico de duas transferências. Ele retorna o rótulo do nó Account e o apelido 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 em um caminho de gráfico. Para
semântica detalhada, consulte PATH_LENGTH.
Exemplo
Essa consulta encontra o número de arestas em um caminho de gráfico que contém de 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 de gráfico tem nós repetidos. Ele retorna
TRUE se uma repetição for encontrada. Caso contrário, retorna FALSE. Para ver a semântica detalhada, consulte IS_ACYCLIC.
Exemplo
Essa consulta verifica se o 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 |
| FALSO | 16,20,16 |
| TRUE | 7,16,20 |
| TRUE | 7,16,20 |
| FALSO | 20,16,20 |
IS_TRAIL
A função IS_TRAIL verifica se um caminho de gráfico tem arestas repetidas. Ele retorna
TRUE se uma repetição for encontrada. Caso contrário, retorna FALSE. Para ver a semântica detalhada, consulte IS_TRAIL.
Exemplo
Essa consulta verifica se o 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 |
|---|---|
| FALSO | 16,20,16 |
| TRUE | 7,16,20 |
| TRUE | 7,16,20 |
Modos de caminho
No Spanner Graph, o comportamento padrão é retornar todos os caminhos, incluindo aqueles com nós e arestas repetidos. Você pode usar os seguintes modos de caminho para incluir ou excluir caminhos com nós e arestas repetidos. Para semântica detalhada, consulte a documentação do modo de caminho.
WALK
O modo de caminho WALK retorna todos os caminhos, incluindo aqueles com nós e arestas repetidos. WALK é o modo de caminho padrão.
Exemplo
A consulta a seguir demonstra o uso do modo de caminho WALK em um 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 caminhos com nós repetidos.
Exemplo
A consulta a seguir demonstra o uso do modo de caminho ACYCLIC em um 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 caminhos com arestas repetidas.
Exemplo
A consulta a seguir demonstra o uso do modo de caminho TRAIL em um 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 da pesquisa de caminho
É possível usar um prefixo de pesquisa de caminho para restringir um padrão de caminho e retornar 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 retorna 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 houver mais de um caminho mais curto por partição, retorne qualquer um deles.
Exemplo
A consulta a seguir 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 Regras de conversão de GRAPH_PATH.
Exemplo de caso de uso
No exemplo de caso de uso a seguir, você encontra todas as contas que foram encaminhadas
por uma a três contas, do ID da conta 20.
GRAPH FinGraph
MATCH p = (start:Account {id: 20})-[:Transfers]->{1,3}(dst:Account)
RETURN DISTINCT dst.id AS dst;
Result
| dst |
|---|
| 7 |
| 16 |
| 20 |
No entanto, uma consulta que retorna ao ID da conta 20 pode ser muito ampla porque começa com o ID da conta 20. Para mostrar resultados mais específicos, você pode
forçar sua consulta a mostrar apenas caminhos de gráficos acíclicos sem nós repetidos.
Para isso, você pode:
- Use
MATCH p = ACYCLIC <path_pattern>; ou - Aplicar um filtro
IS_ACYCLIC(p)na consulta
A consulta a seguir 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;
Result
| dst |
|---|
| 7 |
| 16 |
Se quiser saber a primeira conta pela qual o dinheiro foi transferido, execute 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;
Essa consulta não é convencional porque introduz uma nova variável no caminho quantificado usando nexts para receber o resultado. Com as variáveis de caminho, é possível 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;
Usar NODES(p) retorna todos os nós ao longo do caminho. Como a primeira conta de nó é especificada como start, a próxima (no primeiro deslocamento) é a primeira conta em que o dinheiro é transferido.
Result
| dst | unique_starts |
|---|---|
| 7 | 16, 7 |
Os caminhos são mais úteis quando há vários caminhos quantificados. Você pode adicionar uma restrição para que os caminhos encontrados em start passem 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 instrução MATCH tenha mudado, o restante da consulta não precisa ser alterado. Sem usar variáveis de caminho, há casos em que não é possível
para o Spanner saber estaticamente qual caminho quantificado inspecionar.
Usando uma variável de caminho, é possível receber 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;
Result
| dst | participating_neighbor_nodes | transfer_amounts |
|---|---|---|
| 16 | 7 | 600 |
| 16 | 7 | 800 |