本頁面說明如何在 Spanner Graph 中使用圖形路徑。
在圖形資料庫中,圖形路徑資料型別代表交錯的節點和邊緣序列,並顯示這些節點和邊緣的關係。如要進一步瞭解路徑資料類型,請參閱「圖形路徑類型」。
使用 Spanner Graph Language (GQL),您可以建構圖形路徑並對其執行查詢。本文中的範例使用與「設定及查詢 Spanner Graph」頁面相同的 Spanner Graph 結構定義。
建構圖形路徑
您可以在圖表模式中建立路徑變數,或使用 PATH
函式,建構圖表路徑。
建議您使用路徑變數建構圖形路徑。建立路徑變數的格式如下:
MATCH p = PATH_PATTERN
詳情請參閱「圖形模式」。
範例
在以下範例中,查詢會找出 FinGraph
內帳戶間的轉帳模式。
GRAPH FinGraph
MATCH p = (src:Account {id: 16})-[t:Transfers]->{2}(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
邊緣的量,可能介於 src
和 mid
之間,或介於 mid
和 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;
結果
src | dst | second_edge_amount |
---|---|---|
7 | 16 | 300 |
NODES
NODES
函式會傳回圖形路徑中的所有節點。如需詳細語意,請參閱 NODES
。
範例
這項查詢會找出兩筆轉移作業的圖表路徑,然後傳回代表路徑的 JSON 清單。
GRAPH FinGraph
MATCH p = (src:Account)-[t:Transfers]->{2}(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)-[t:Transfers]->{2}(dst:Account)
RETURN IS_ACYCLIC(p) AS is_acyclic_path,
ARRAY_TRANSFORM(NODES(p), n->n.id) AS account_ids;
結果
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
IS_TRAIL
函式會檢查圖形路徑是否含有重複邊緣。如果找到重複項目,則傳回 TRUE
,否則傳回 FALSE
。如需詳細語意,請參閱 IS_TRAIL
。
範例
這項查詢會檢查這個圖形路徑是否有重複的邊緣。
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
結果
is_trail_path | transfer_ids |
---|---|
FALSE | 16,20,16 |
TRUE | 7,16,20 |
TRUE | 7,16,20 |
路徑模式
在 Spanner Graph 中,預設行為是傳回所有路徑,包括具有重複節點和邊緣的路徑。您可以使用下列路徑模式,納入或排除具有重複節點和邊緣的路徑。如需詳細語意,請參閱「路徑模式」說明文件。
WALK
WALK
路徑模式會傳回所有路徑,包括含有重複節點和邊緣的路徑。WALK
是預設路徑模式。
範例
下列查詢示範如何在量化路徑模式上使用 WALK
路徑模式。結果中的第一個路徑有重複的邊緣。
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
結果
transfer_ids |
---|
16,20,16 |
7,16,20 |
7,16,20 |
ACYCLIC
ACYCLIC
路徑模式會篩除含有重複節點的路徑。
範例
下列查詢示範如何在量化路徑模式上使用 ACYCLIC
路徑模式。系統會篩除具有相同 src
和 dst
節點的路徑。
GRAPH FinGraph
MATCH p = ACYCLIC (src:Account)-[t:Transfers]->{2}(dst:Account)
RETURN ARRAY_TRANSFORM(NODES(p), n->n.id) AS account_ids
結果
account_ids |
---|
16,20,7 |
20,7,16 |
20,7,16 |
7,16,20 |
7,16,20 |
TRAIL
TRAIL
路徑模式會篩除有重複邊緣的路徑。
範例
下列查詢示範如何在量化路徑模式上使用 TRAIL
路徑模式。系統會濾除有重複邊緣的路徑。
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
結果
transfer_ids |
---|
7,16,20 |
7,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 |