使用路徑

本頁面說明如何在 Spanner 圖表中使用圖表路徑。

在圖形資料庫中,圖形路徑資料類型代表節點與邊緣交錯的序列,並顯示這些節點和邊緣的關聯方式。如要進一步瞭解路徑資料類型,請參閱「圖形路徑類型」。

您可以使用 Spanner Graph Language (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;

結果

節點
[{"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

範例

這項查詢會找出圖表路徑中包含一到三次轉移的邊數量。

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 中,預設行為是傳回所有路徑,包括含有重複節點和邊的路徑。您可以使用下列路徑模式,加入或排除含有重複節點和邊緣的路徑。如需詳細語意說明,請參閱 Path 模式說明文件。

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 路徑搜尋前置字串會傳回與每個資料分割區模式相符的最短路徑 (邊緣數量最少的路徑)。如果每個區隔都有多個最短路徑,則會傳回其中任一條路徑。

範例

下列查詢會比對每對 [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 中的一到三個帳戶進行路由。

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

後續步驟