경로 작업

이 페이지에서는 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를 참고하세요.

예시

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

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 경로 모드를 사용하는 방법을 보여줍니다. 결과의 첫 번째 경로는 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 경로 검색 접두사는 각 데이터 파티션의 패턴과 일치하는 가장 짧은 경로 (가장 적은 수의 간선이 있는 경로)를 반환합니다. 파티션당 최단 경로가 두 개 이상인 경우 그중 하나를 반환합니다.

예시

다음 쿼리는 각 [a, b] 쌍 간의 모든 경로를 일치시킵니다.

GRAPH FinGraph
MATCH p = ANY SHORTEST (a:Account)-[t:Transfers]->{1,4}(b:Account)
WHERE a.is_blocked
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

다음 단계