경로 사용

이 페이지에서는 Spanner Graph에서 그래프 경로를 사용하는 방법을 설명합니다.

그래프 데이터베이스에서 그래프 경로 데이터 유형은 에지로 인터리브 처리된 노드의 시퀀스를 나타내며 이러한 노드와 에지의 관계를 보여줍니다. 경로 데이터 유형에 대한 자세한 내용은 그래프 경로 유형을 참조하세요.

Spanner Graph 언어(GQL)를 사용하면 그래프 경로를 구성하고 그래프 경로에서 쿼리를 수행할 수 있습니다. 이 문서의 예시에서는 Spanner Graph 설정 및 쿼리 페이지에 있는 스키마와 동일한 Spanner Graph 스키마를 사용합니다.

그래프 경로 구성

그래프 패턴에서 또는 PATH 함수를 사용하여 경로 변수를 만들어 그래프 경로를 구성할 수 있습니다.

경로 변수를 사용하여 그래프 경로를 구성하는 것이 좋습니다. 경로 변수를 만드는 형식은 다음과 같습니다.

MATCH p = PATH_PATTERN

자세한 내용은 그래프 패턴을 참조하세요.

다음 예시에서는 쿼리가 FinGraph 내 계정 간의 송금 패턴을 찾습니다.

GRAPH FinGraph
MATCH p = (src:Account {id: 16})-[t1:Transfers]->(mid:Account)-[t2:Transfers]->
  (dst:Account {id: 7})
RETURN TO_JSON(p) AS full_path;

결과

full_path
[{"identifier": ..., "properties": {"id": 16, ...}, ...}, {"identifier": ..., "properties": {"amount": 300.0, ...}, ...}, ...]

이 결과는 쿼리가 데이터베이스에서 Account -> Transfers -> Account 패턴을 찾았음을 나타냅니다.

그래프 경로 쿼리

다음 경로별 함수를 사용하여 그래프 경로를 쿼리할 수 있습니다. Spanner Graph 쿼리에 대한 자세한 내용은 쿼리 개요를 참조하세요.

EDGES

EDGES 함수는 그래프 경로의 모든 에지를 반환합니다. 자세한 시맨틱스는 EDGES를 참조하세요.

이 쿼리는 중간 계정을 통과하는 두 계정 간의 경로를 찾습니다. srcmid 사이 또는 middst 사이의 경로에서 두 번째 Transfers 에지 크기를 반환합니다.

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;

결과

src dst second_edge_amount
7 16 300

NODES

NODES 함수는 그래프 경로의 모든 노드를 반환합니다. 자세한 시맨틱스는 NODES를 참조하세요.

이 쿼리는 두 전송의 그래프 경로를 찾은 후 경로를 나타내는 JSON 목록을 반환합니다.

GRAPH FinGraph
MATCH p = (src:Account)-[t1:Transfers]->(mid:Account)-[t2:Transfers]->(dst:Account)
RETURN TO_JSON(NODES(p)) AS nodes;

결과

nodes
[{"identifier": "...", "properties": {"id": 16}, ...}, {"identifier": "...", "properties": {"id": 20, ...}, ...]
...

PATH_FIRST

PATH_FIRST 함수는 그래프 경로에서 첫 번째 노드를 찾습니다. 자세한 시맨틱스는 PATH_FIRST를 참조하세요.

이 쿼리는 두 전송의 그래프 경로에서 첫 번째 노드를 찾습니다. Account 노드 라벨과 계정 닉네임을 반환합니다.

GRAPH FinGraph
MATCH p = -[:Transfers]->{1,3}(dst:Account{id: 7})
RETURN DISTINCT PATH_FIRST(p).id AS can_reach_target;

결과

can_reach_target
7
16
20

PATH_LAST

PATH_LAST 함수는 그래프 경로의 마지막 노드를 찾습니다. 자세한 시맨틱스는 PATH_LAST를 참조하세요.

이 쿼리는 두 전송의 그래프 경로에서 마지막 노드를 찾습니다. Account 노드 라벨과 계정 닉네임을 반환합니다.

GRAPH FinGraph
MATCH p =(start:Account{id: 7})-[:Transfers]->{1,3}
RETURN DISTINCT PATH_LAST(p).id as can_reach_target;

결과

can_reach_target
7
16
20

PATH_LENGTH

PATH_LENGTH 함수는 그래프 경로에서 에지 수를 찾습니다. 자세한 시맨틱스는 PATH_LENGTH를 참조하세요.

이 쿼리는 전송 1~3개가 포함된 그래프 경로에서 에지 수를 찾습니다.

GRAPH FinGraph
MATCH p = (src:Account)-[e:Transfers]->{1,3}(dst:Account)
RETURN PATH_LENGTH(p) AS num_transfers, COUNT(*) AS num_paths;

결과

num_transfers num_paths
1 5
2 7
3 11

IS_ACYCLIC

IS_ACYCLIC 함수는 그래프 경로에 반복 노드가 있는지 확인합니다. 반복이 발견되면 TRUE를 반환하고 그렇지 않으면 FALSE를 반환합니다. 자세한 시맨틱스는 IS_ACYCLIC을 참조하세요.

이 쿼리는 이 그래프 경로에 반복되는 노드가 있는지 확인합니다.

GRAPH FinGraph
MATCH p = (src:Account)-[t1:Transfers]->(mid:Account)-[t2:Transfers]->(dst:Account)
RETURN IS_ACYCLIC(p) AS is_acyclic_path, src.id AS source_account_id,
  mid.id AS mid_account_id, dst.id AS dst_account_id;

결과

is_acyclic_path source_account_id mid_account_id dst_account_id
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

IS_TRAIL 함수는 그래프 경로에 반복 에지가 있는지 확인합니다. 반복이 발견되면 TRUE를 반환하고 그렇지 않으면 FALSE를 반환합니다. 자세한 시맨틱스는 IS_TRAIL을 참조하세요.

이 쿼리는 이 그래프 경로에 반복되는 에지가 있는지 확인합니다.

GRAPH FinGraph
MATCH p = (src:Account)-[t1:Transfers]->(mid1:Account)-[t2:Transfers]->
  (mid2:Account)-[t3:Transfers]->(dst:Account)
WHERE src.id < dst.id
RETURN IS_TRAIL(p) AS is_trail_path, t1.id AS t1_id, t2.id AS t2_id, t3.id AS t3_id;

결과

is_trail_path t1_id t2_id t3_id
FALSE 16 20 16
TRUE 7 16 20
TRUE 7 16 20

경로 모드

Spanner Graph에서 기본 동작은 반복 노드와 에지가 있는 경로를 포함한 모든 경로를 반환하는 것입니다. 다음 경로 모드를 사용하여 반복 노드와 에지가 있는 경로를 포함하거나 제외할 수 있습니다. 자세한 시맨틱스는 경로 모드 문서를 참조하세요.

WALK

WALK 경로 모드는 반복 노드와 에지가 있는 경로를 포함한 모든 경로를 반환합니다. WALK는 기본 경로 모드입니다.

다음 쿼리는 수치화되지 않은 경로 패턴에서 WALK 경로 모드를 사용하는 방법을 보여줍니다. 결과의 첫 번째 경로는 t1t3의 같은 에지를 사용합니다.

GRAPH FinGraph
MATCH p = WALK (src:Account)-[t1:Transfers]->(mid1:Account)-[t2:Transfers]->
  (mid2:Account)-[t3:Transfers]->(dst:Account)
WHERE src.id < dst.id
RETURN t1.id AS transfer1_id, t2.id AS transfer2_id, t3.id AS transfer3_id;

결과

transfer1_id transfer2_id transfer3_id
16 20 16
7 16 20
7 16 20

ACYCLIC

ACYCLIC 경로 모드는 반복 노드가 있는 경로를 필터링합니다.

다음 쿼리는 수치화되지 않은 경로 패턴에서 ACYCLIC 경로 모드를 사용하는 방법을 보여줍니다. srcdst 노드가 같은 경로가 필터링됩니다.

GRAPH FinGraph
MATCH p = ACYCLIC (src:Account)-[t1:Transfers]->(mid:Account)-[t2:Transfers]->(dst:Account)
RETURN src.id AS account1_id, mid.id AS account2_id, dst.id AS account3_id;

결과

account1_id account2_id account3_id
20 7 16
20 7 16
7 16 20
7 16 20
16 20 7

TRAIL

TRAIL 경로 모드는 반복 에지가 있는 경로를 필터링합니다.

다음 쿼리는 수치화되지 않은 경로 패턴에서 TRAIL 경로 모드를 사용하는 방법을 보여줍니다. t1t3 에지가 같은 경로가 필터링됩니다.

GRAPH FinGraph
MATCH p = TRAIL (src:Account)-[t1:Transfers]->(mid1:Account)-[t2:Transfers]->
  (mid2:Account)-[t3:Transfers]->(dst:Account)
RETURN
  t1.id AS transfer1_id, t2.id AS transfer2_id, t3.id AS transfer3_id;

결과

transfer1_id transfer2_id transfer3_id
16 20 7
16 20 7
20 7 16
20 7 16
7 16 20
7 16 20
7 16 20
7 16 20
20 16 20

경로 검색 프리픽스

경로 검색 프리픽스를 사용하여 경로 패턴을 제한해 각 데이터 파티션에서 최단 경로를 반환할 수 있습니다. 자세한 시맨틱스는 경로 검색 프리픽스를 참조하세요.

ANY SHORTEST

ANY SHORTEST 경로 검색 프리픽스는 각 데이터 파티션의 패턴과 일치하는 최단 경로(에지 수가 가장 적은 경로)를 반환합니다. 파티션당 최단 경로가 2개 이상 있으면 그중 하나가 반환됩니다.

다음 쿼리는 각 [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;

결과

account1_id total_amount account2_id
16 500 16
16 800 7
16 300 20

변환 규칙

자세한 내용은 GRAPH_PATH 변환 규칙을 참조하세요.

사용 사례 예시

다음 사용 사례 예시에서는 모든 계정이 계정 ID 20에서 계정 1~3개를 통해 라우팅된 것을 확인할 수 있습니다.

GRAPH FinGraph
MATCH p = (start:Account {id: 20})-[:Transfers]->{1,3}(dst:Account)
RETURN DISTINCT dst.id AS dst;

결과

dst
7
16
20

그러나 계정 ID 20으로 반환되는 쿼리는 계정 ID 20으로 시작하기 때문에 지나치게 광범위한 쿼리일 수 있습니다. 더 구체적인 결과를 표시하려면 반복 노드가 없는 비순환 그래프 경로만 표시하도록 쿼리를 적용하면 됩니다. 이렇게 하려면 다음을 수행하면 됩니다.

  • MATCH p = ACYCLIC <path_pattern> 사용
  • 쿼리에 IS_ACYCLIC(p) 필터 적용

다음 쿼리는 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;

결과

dst
7
16

금액이 송금되는 첫 번째 계정을 알고 싶으면 다음 쿼리를 실행하면 됩니다.

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;

이 쿼리는 nexts를 사용하여 결과를 가져오는 정량화된 경로 내에 새 변수를 도입하므로 일반적이지 않습니다. 경로 변수를 사용하면 쿼리를 간소화할 수 있습니다.

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;

NODES(p)를 사용하면 경로의 모든 노드가 반환됩니다. 첫 번째 노드 계정이 start로 지정되므로 다음 계정(첫 번째 오프셋)이 송금되는 첫 번째 계정입니다.

결과

dst unique_starts
7 16, 7

경로는 정량화된 경로가 여러 개 있는 경우에 더 유용합니다. start에서 찾은 경로가 계정 ID 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;

MATCH 문이 변경되었지만 나머지 쿼리를 변경할 필요가 없습니다. 경로 변수를 사용하지 않으면 Spanner에서 검사할 정량화된 경로를 정적으로 알 수 없는 경우가 있습니다.

경로 변수를 사용하면 모든 송금 총액을 가져올 수 있습니다.

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;

결과

dst participating_neighbor_nodes transfer_amounts
16 7 600
16 7 800

다음 단계