本文說明如何在 Spanner Graph 中查詢資源圖。本節的範例會使用您在「設定及查詢 Spanner Graph」一文中建立的圖形結構定義,如下圖所示:
執行 Spanner Graph 查詢
您可以透過下列方式執行 Spanner Graph 查詢:
Google Cloud 控制台
在 Spanner Studio 頁面提交查詢。如要存取「Spanner Studio」頁面,請在「資料庫總覽」頁面或「資料表總覽」頁面中,按一下「Spanner Studio」。如要進一步瞭解如何存取 Spanner Studio,請參閱「使用 Google Cloud 控制台管理資料」。
gcloud spanner
指令列工具使用
gcloud spanner databases execute-sql
指令提交指令。executeSql
和executeStreamingSql
REST APIExecuteSql
和ExecuteStreamingSql
RPC API
以視覺化方式呈現 Spanner Graph 查詢結果
如果查詢以 JSON 格式傳回完整節點,您可以在 Spanner Studio 中將 Spanner 圖形查詢結果以視覺化方式呈現。詳情請參閱「使用 Spanner 圖表視覺化資料」。
Spanner Graph 查詢結構
本節將詳細說明每個查詢元件。
以下範例說明 Spanner 圖形查詢的基本結構。
Spanner Graph 可讓您在資料庫中建立多個圖形。查詢會先使用 GRAPH
子句指定目標圖表 FinGraph
。
圖表模式比對
圖表模式比對功能可找出圖表中的特定模式。最基本的模式是元素模式 (節點模式和邊模式),可與圖表元素 (分別為節點和邊) 相符。元素模式可組合成路徑模式和更複雜的模式。
節點模式
節點模式是與圖表中的節點相符的模式。這個模式由一組相符的括號組成,可視需要包含圖表模式變數、標籤運算式和資源篩選器。
尋找所有節點
下列查詢會傳回圖表中的所有節點。變數 n
稱為圖表模式變數,會繫結至相符的節點。在這種情況下,節點模式會比對圖表中的所有節點。
GRAPH FinGraph
MATCH (n)
RETURN LABELS(n) AS label, n.id;
結果
查詢會傳回 label
和 id
,如下所示:
標籤 | id |
---|---|
帳戶 | 7 |
帳戶 | 16 |
帳戶 | 20 |
人物 | 1 |
人物 | 2 |
人物 | 3 |
找出所有含有特定標籤的節點
下列查詢會比對圖表中所有具有 Person
label 的節點。查詢會傳回相符節點的 label
和 id
、name
屬性。
GRAPH FinGraph
MATCH (p:Person)
RETURN LABELS(p) AS label, p.id, p.name;
結果
標籤 | id | 名稱 |
---|---|---|
人物 | 1 | Alex |
人物 | 2 | Dana |
人物 | 3 | Lee |
找出符合標籤運算式的所有節點
您可以使用一或多個邏輯運算子建立標籤運算式。
下列查詢會比對圖表中具有 Person
或 Account
標籤的所有節點。圖表模式變數 n
公開的屬性集合,是具有 Person
或 Account
標籤的節點公開的屬性超集。
GRAPH FinGraph
MATCH (n:Person|Account)
RETURN LABELS(n) AS label, n.id, n.birthday, n.create_time;
- 在結果中,所有節點都有
id
屬性。 - 與
Account
標籤相符的節點具有create_time
屬性,但沒有birthday
屬性。針對這類節點的birthday
屬性,系統會傳回NULL
。 - 與
Person
標籤相符的節點具有birthday
屬性,但沒有create_time
屬性。針對這類節點的create_time
屬性,系統會傳回NULL
。
結果
標籤 | id | 生日 | create_time |
---|---|---|---|
帳戶 | 7 | 空值 | 2020-01-10T14:22:20.222Z |
帳戶 | 16 | 空值 | 2020-01-28T01:55:09.206Z |
帳戶 | 20 | 空值 | 2020-02-18T13:44:20.655Z |
人物 | 1 | 1991-12-21T08:00:00Z | 空值 |
人物 | 2 | 1980-10-31T08:00:00Z | 空值 |
人物 | 3 | 1986-12-07T08:00:00Z | 空值 |
如要進一步瞭解標籤運算式規則,請參閱「標籤運算式」。
找出符合標籤運算式和屬性篩選器的所有節點
以下查詢會比對圖表中所有具有 Person
標籤的節點,且屬性 id
等於 1
。
GRAPH FinGraph
MATCH (p:Person {id: 1})
RETURN LABELS(p) AS label, p.id, p.name, p.birthday;
結果
標籤 | id | 名稱 | 生日 |
---|---|---|---|
人物 | 1 | Alex | 1991-12-21T08:00:00Z |
您可以使用 WHERE
子句,針對標籤和屬性建立更複雜的篩選條件。
以下查詢會比對圖表中所有具有 Person
標籤的節點,且屬性 birthday
會位於 1990-01-10
之前。
GRAPH FinGraph
MATCH (p:Person WHERE p.birthday < '1990-01-10')
RETURN LABELS(p) AS label, p.name, p.birthday;
結果
標籤 | 名稱 | 生日 |
---|---|---|
人物 | Dana | 1980-10-31T08:00:00Z |
人物 | Lee | 1986-12-07T08:00:00Z |
邊緣模式
邊緣模式會比對節點之間的邊緣或關係。邊緣圖案會以方括號 []
括住,並使用符號 -
、->
或 <-
指示方向。
與節點模式類似,圖表模式變數會用來綁定至相符的邊緣元素。
找出所有標籤相符的邊
下列查詢會傳回圖表中所有具有 Transfers
標籤的邊。圖形模式變數 e
會繫結至相符的邊緣。
GRAPH FinGraph
MATCH -[e:Transfers]->
RETURN e.Id as src_account, e.order_number
結果
src_account | order_number |
---|---|
7 | 304330008004315 |
7 | 304120005529714 |
16 | 103650009791820 |
20 | 304120005529714 |
20 | 302290001255747 |
找出符合標籤運算式和屬性篩選條件的所有邊
與節點模式類似,邊緣模式可使用標籤運算式、屬性規格和 WHERE
子句,如以下查詢所示。這項查詢會找出標示為 Transfers
且符合指定 order_number
的所有邊。
GRAPH FinGraph
MATCH -[e:Transfers {order_number: "304120005529714"}]->
RETURN e.Id AS src_account, e.order_number
結果
src_account | order_number |
---|---|
7 | 304120005529714 |
20 | 304120005529714 |
使用任一方向邊緣模式找出所有邊緣
雖然 Spanner 圖形中的所有邊都是有向的,但您可以在查詢中使用 any
direction
邊緣模式 -[]-
,以便在任一方向比對邊緣。
下列查詢會找出所有涉及已封鎖帳戶的轉帳。
GRAPH FinGraph
MATCH (account:Account)-[transfer:Transfers]-(:Account {is_blocked:true})
RETURN transfer.order_number, transfer.amount;
結果
order_number | amount |
---|---|
304330008004315 | 300 |
304120005529714 | 100 |
103650009791820 | 300 |
302290001255747 | 200 |
路徑模式
路徑模式是由交替的節點和邊緣模式建立而成。
使用路徑模式,從具有指定標籤和屬性篩選器的節點中找出所有路徑
以下查詢會找出所有從 Person
擁有的帳戶啟動的轉帳作業,其中 id
等於 2
。
每個相符結果都代表從 Person
{id: 2}
開始的路徑,經由使用 Owns
邊緣的連結 Account
,進入使用 Transfers
邊緣的另一個 Account
。
GRAPH FinGraph
MATCH
(p:Person {id: 2})-[:Owns]->(account:Account)-[t:Transfers]->
(to_account:Account)
RETURN
p.id AS sender_id, account.id AS from_id, to_account.id AS to_id;
結果
sender_id | from_id | to_id |
---|---|---|
2 | 20 | 7 |
2 | 20 | 16 |
量化路徑模式
量化模式可讓模式在指定範圍內重複出現。
比對量化邊緣圖案
下列查詢會找出所有目標帳戶,這些帳戶與來源 Account
之間的轉移次數介於 1 到 3 次之間,但不包含來源帳戶本身。id
等於 7
。
邊緣模式的後置量詞 {1, 3}
。
GRAPH FinGraph
MATCH (src:Account {id: 7})-[e:Transfers]->{1, 3}(dst:Account)
WHERE src != dst
RETURN src.id AS src_account_id, ARRAY_LENGTH(e) AS path_length, dst.id AS dst_account_id;
結果
src_account_id | path_length | dst_account_id |
---|---|---|
7 | 1 | 16 |
7 | 1 | 16 |
7 | 1 | 16 |
7 | 3 | 16 |
7 | 3 | 16 |
7 | 2 | 20 |
7 | 2 | 20 |
上一個範例使用 ARRAY_LENGTH
函式存取 group variable
e
。詳情請參閱「存取群組變數」。
範例結果中的部分資料列會重複,因為相同一組符合模式的 src
和 dst
帳戶之間可能有多個路徑。
比對量化路徑模式
下列查詢會透過遭封鎖的中介帳戶,找出具有一到兩個 Transfers
邊緣的 Account
節點之間的路徑。
使用括號的路徑模式會經過量化,並在括號中使用 WHERE
子句,指定重複模式的條件。
GRAPH FinGraph
MATCH
(src:Account)
((a:Account)-[:Transfers]->(b:Account {is_blocked:true}) WHERE a != b){1,2}
-[:Transfers]->(dst:Account)
RETURN src.id AS src_account_id, dst.id AS dst_account_id;
結果
src_account_id | dst_account_id |
---|---|
7 | 20 |
7 | 20 |
20 | 20 |
群組變數
在量化模式中宣告的圖表模式變數,在量化模式外存取時會視為群組變數,並繫結至一組相符的圖表元素。
您可以將群組變數當作陣列存取,在相符路徑中以圖表元素的顯示順序保留圖表元素。您可以使用水平匯總功能匯總群組變數。
存取群組變數
在以下範例中,變數 e
的存取方式如下:
- 圖表模式變數,繫結至
WHERE
子句e.amount > 100
(在量化模式中) 的單一邊緣。 - 群組變數會繫結至
RETURN
陳述式中ARRAY_LENGTH(e)
的邊緣元素陣列 (在量化模式之外)。 - 群組變數會繫結至邊緣元素陣列,並由量化模式外的
SUM(e.amount)
匯總。這是水平匯總的範例。
GRAPH FinGraph
MATCH
(src:Account {id: 7})-[e:Transfers WHERE e.amount > 100]->{0,2}
(dst:Account)
WHERE src.id != dst.id
LET total_amount = SUM(e.amount)
RETURN
src.id AS src_account_id, ARRAY_LENGTH(e) AS path_length,
total_amount, dst.id AS dst_account_id;
結果
src_account_id | path_length | total_amount | dst_account_id |
---|---|---|---|
7 | 1 | 300 | 16 |
7 | 2 | 600 | 20 |
Any 和 Any Shortest paths
如要限制每個共用相同來源和目的地節點的路徑群組中,所比對的路徑數量,您可以使用 ANY
或 ANY SHORTEST
路徑搜尋前置字串。您只能在整個路徑模式前方套用這些前置字串,且不得在括號內套用。
使用「ANY」比對
以下查詢會找出所有可到達的專屬帳戶,這些帳戶與指定 Account
節點相距一或兩個 Transfers
。
ANY
路徑搜尋前置字串可確保只傳回不重複的 src
和 dst
Account
節點之間的路徑。在以下範例中,雖然您可以透過兩個不同的路徑,從來源 Account
節點使用 {id: 16}
存取 Account
節點,但結果只包含一個路徑。
GRAPH FinGraph
MATCH ANY (src:Account {id: 7})-[e:Transfers]->{1,2}(dst:Account)
LET ids_in_path = ARRAY_CONCAT(ARRAY_AGG(e.Id), [dst.Id])
RETURN src.id AS src_account_id, dst.id AS dst_account_id, ids_in_path;
結果
src_account_id | dst_account_id | ids_in_path |
---|---|---|
7 | 16 | 7,16 |
7 | 20 | 7,16,20 |
圖表模式
圖表模式包含一或多個路徑模式,以半形逗號 (,
) 分隔。圖表模式可包含 WHERE
子句,讓您存取路徑模式中的所有圖表模式變數,以便建立篩選條件。每個路徑模式都會產生一組路徑。
使用圖表模式進行比對
以下查詢會找出涉及交易金額超過 200 的間接帳戶及其擁有者,這些帳戶會將資金從來源帳戶轉移到遭封鎖的帳戶。
下列路徑模式會形成圖表模式:
- 第一個模式會找出從一個帳戶轉移至遭封鎖帳戶的路徑,中間會使用一個帳戶。
- 第二個模式會找出從帳戶到擁有者的路徑。
變數 interm
會做為兩個路徑模式之間的共同連結,這需要 interm
在兩個路徑模式中參照相同的元素節點。這會根據 interm
變數建立相等聯結作業。
GRAPH FinGraph
MATCH
(src:Account)-[t1:Transfers]->(interm:Account)-[t2:Transfers]->(dst:Account),
(interm)<-[:Owns]-(p:Person)
WHERE dst.is_blocked = TRUE AND t1.amount > 200 AND t2.amount > 200
RETURN
src.id AS src_account_id, dst.id AS dst_account_id,
interm.id AS interm_account_id, p.id AS owner_id;
結果
src_account_id | dst_account_id | interm_account_id | owner_id |
---|---|---|---|
20 | 16 | 7 | 1 |
線性查詢陳述式
您可以將多個圖表陳述式鏈結在一起,形成線性查詢陳述式。陳述式會按照查詢中顯示的順序執行。
- 每個陳述式都會將先前陳述式的輸出內容做為輸入內容。第一個陳述式的輸入內容為空白。
- 最後一個陳述式的輸出內容就是最終結果。
查看可轉入封鎖帳戶的金額上限
以下查詢會找出轉出至已封鎖帳戶的金額最高的帳戶和擁有者。
GRAPH FinGraph
MATCH (src_account:Account)-[transfer:Transfers]->(dst_account:Account {is_blocked:true})
ORDER BY transfer.amount DESC
LIMIT 1
MATCH (src_account:Account)<-[owns:Owns]-(owner:Person)
RETURN src_account.id AS account_id, owner.name AS owner_name;
下表說明如何將中間結果沿著陳述式傳遞。為簡化說明,我們只會顯示中繼結果的部分屬性。
陳述式 | 中間結果 (簡稱) | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
MATCH (src_account:Account) -[transfer:Transfers]-> (dst_account:Account {is_blocked:true}) |
|
||||||||||||
ORDER BY transfer.amount DESC |
|
||||||||||||
LIMIT 1 |
|
||||||||||||
MATCH (src_account:Account) <-[owns:Owns]- (owner:Person) |
|
||||||||||||
RETURN src_account.id AS account_id, owner.name AS owner_name |
|
結果
account_id | owner_name |
---|---|
7 | Alex |
回傳敘述
傳回陳述式會定義從相符模式傳回的內容。可存取圖表模式變數,包含運算式和其他子句,例如 ORDER_BY、GROUP_BY。請參閱 RETURN
陳述式。
Spanner Graph 不支援以圖形元素做為查詢結果。如要傳回整個圖表元素,請使用 TO_JSON
函式或 SAFE_TO_JSON
函式。在上述兩個函式中,我們建議您使用 SAFE_TO_JSON
。
以 JSON 格式傳回圖表元素
GRAPH FinGraph
MATCH (n:Account {id: 7})
-- Returning a graph element in the final results is NOT allowed. Instead, use
-- the TO_JSON function or explicitly return the graph element's properties.
RETURN TO_JSON(n) AS n;
GRAPH FinGraph
MATCH (n:Account {id: 7})
-- Certain fields in the graph elements, such as TOKENLIST, can't be returned
-- in the TO_JSON function. In those cases, use the SAFE_TO_JSON function instead.
RETURN SAFE_TO_JSON(n) AS n;
結果
n |
---|
{"identifier":"mUZpbkdyYXBoLkFjY291bnQAeJEO","kind":"node","labels":["Account"],"properties":{"create_time":"2020-01-10T14:22:20.222Z","id":7,"is_blocked":false,"nick_name":"Vacation Fund"}} |
使用 NEXT 關鍵字撰寫更大型的查詢
您可以使用 NEXT
關鍵字將多個圖形線性查詢陳述式連結在一起。第一個線性查詢陳述式的輸入內容為空白。每個線性查詢陳述式的輸出內容都會成為下一個線性查詢陳述式的輸入內容。
以下範例會將多個圖形線性陳述式連結在一起,找出接收最多轉帳的帳戶擁有者。請注意,您可以使用相同的變數 (本例中的 account
),在多個線性陳述式中參照相同的圖表元素。
GRAPH FinGraph
MATCH (:Account)-[:Transfers]->(account:Account)
RETURN account, COUNT(*) AS num_incoming_transfers
GROUP BY account
ORDER BY num_incoming_transfers DESC
LIMIT 1
NEXT
MATCH (account:Account)<-[:Owns]-(owner:Person)
RETURN account.id AS account_id, owner.name AS owner_name, num_incoming_transfers;
結果
account_id | owner_name | num_incoming_transfers |
---|---|---|
16 | Lee | 3 |
函式和運算式
您可以在 Spanner 圖表查詢中使用所有 GoogleSQL 函式 (匯總和純量函式)、運算子和條件式運算式。Spanner Graph 也支援圖形專屬函式和運算子。
內建函式和運算子
PROPERTY_EXISTS(n, birthday)
:傳回n
是否公開birthday
屬性。LABELS(n)
:傳回圖表結構定義中定義的n
標籤。PROPERTY_NAMES(n)
:傳回n
的屬性名稱。TO_JSON(n)
:以 JSON 格式傳回n
。詳情請參閱TO_JSON
函式。
PROPERTY_EXISTS
判定式、LABELS
函式和 TO_JSON
函式,以及 ARRAY_AGG
和 CONCAT
等其他內建函式。
GRAPH FinGraph
MATCH (person:Person)-[:Owns]->(account:Account)
RETURN person, ARRAY_AGG(account.nick_name) AS accounts
GROUP BY person
NEXT
RETURN
LABELS(person) AS labels,
TO_JSON(person) AS person,
accounts,
CONCAT(person.city, ", ", person.country) AS location,
PROPERTY_EXISTS(person, is_blocked) AS is_blocked_property_exists,
PROPERTY_EXISTS(person, name) AS name_property_exists
LIMIT 1;
結果
is_blocked_property_exists | name_property_exists | 標籤 | 帳戶 | 位置 | 使用者圖示 |
---|---|---|---|---|---|
false | 是 | 人物 | [「Vacation Fund」] | 澳洲阿得雷德 | {"identifier":"mUZpbkdyYXBoLlBlcnNvbgB4kQI=","kind":"node","labels":["Person"],"properties":{"birthday":"1991-12-21T08:00:00Z","city":"Adelaide","country":"Australia","id":1,"name":"Alex"}} |
子查詢
「子查詢」是指巢狀在其他查詢中的查詢。以下列出 Spanner 圖表子查詢規則:
- 子查詢會包含在一組大括號
{}
中。 - 子查詢可能會以開頭
GRAPH
子句開始,以便指定範圍內的圖表。指定的圖表不必與外部查詢中使用的圖表相同。 - 如果在子查詢中省略
GRAPH
子句,會發生以下情況:- 系統會根據最接近的外部查詢內容推斷出範圍內的圖表。
- 子查詢必須從圖表模式比對陳述式開始,並使用
MATCH.
- 在子查詢範圍外宣告的圖表模式變數,無法在子查詢中再次宣告,但可在子查詢中的運算式或函式中參照。
使用子查詢找出每個帳戶的轉帳總數
以下查詢說明如何使用 VALUE
子查詢。子查詢會以 VALUE
關鍵字開頭的大括號 {}
包圍。此查詢會傳回從帳戶啟動的轉帳總數。
GRAPH FinGraph
MATCH (p:Person)-[:Owns]->(account:Account)
RETURN p.name, account.id AS account_id, VALUE {
MATCH (a:Account)-[transfer:Transfers]->(:Account)
WHERE a = account
RETURN COUNT(transfer) AS num_transfers
} AS num_transfers;
結果
名稱 | account_id | num_transfers |
---|---|---|
Alex | 7 | 2 |
Dana | 20 | 2 |
Lee | 16 | 1 |
如需支援的子查詢運算式清單,請參閱「Spanner 圖表子查詢」。
查詢參數
您可以使用參數查詢 Spanner Graph。詳情請參閱語法,並瞭解如何在 Spanner 用戶端程式庫中使用參數查詢資料。
以下查詢說明如何使用查詢參數。
GRAPH FinGraph
MATCH (person:Person {id: @id})
RETURN person.name;
同時查詢圖表和資料表
您可以使用圖形查詢搭配 SQL,在單一陳述式中同時存取圖形和資料表的資訊。
GRAPH_TABLE
GRAPH_TABLE
運算子會採用線性圖表查詢,並以表格形式傳回結果,以便順暢地整合至 SQL 查詢。這種互通性可讓您利用非圖表內容豐富圖表查詢結果,反之亦然。
舉例來說,您可以建立 CreditReports
資料表並插入幾份信用報告,如以下範例所示:
CREATE TABLE CreditReports (
person_id INT64 NOT NULL,
create_time TIMESTAMP NOT NULL,
score INT64 NOT NULL,
) PRIMARY KEY (person_id, create_time);
INSERT INTO CreditReports (person_id, create_time, score)
VALUES
(1,"2020-01-10 06:22:20.222", 700),
(2,"2020-02-10 06:22:20.222", 800),
(3,"2020-03-10 06:22:20.222", 750);
接著,透過 GRAPH_TABLE
中的圖表模式比對功能找出相關人士,並將圖表查詢結果與 CreditReports
資料表彙整,以便取得信用分數。
SELECT
gt.person.id,
credit.score AS latest_credit_score
FROM GRAPH_TABLE(
FinGraph
MATCH (person:Person)-[:Owns]->(:Account)-[:Transfers]->(account:Account {is_blocked:true})
RETURN DISTINCT person
) AS gt
JOIN CreditReports AS credit
ON gt.person.id = credit.person_id
ORDER BY credit.create_time;
結果:
person_id | latest_credit_score |
---|---|
1 | 700 |
2 | 800 |
後續步驟
瞭解調整查詢的最佳做法。