圖型匹配讓你能用直覺且視覺化的語法描述你想找到的資料結構。 你不是連接表格,而是寫出看起來像是關係本身的模式——節點由邊連接。 本文將指導您如何在 Microsoft Fabric 中撰寫 GQL 樣式查詢,以應對圖形中常見的情境。
範例中使用社群網路範例資料集。 完整模式語法參考,請參見 GQL 圖形模式。
利用本文學習如何構建並組合節點、邊與路徑模式。 關於現成可調整的任務,如尋找無關聯的鄰居或實體,請參見 撰寫常見的 GQL 查詢。 關於篩選、分組與彙總工作流程,請參見 「篩選與彙整圖資料」。
先決條件
匹配直接關係
基本模式會匹配節點類型、特定邊型態及另一種節點類型。 語法看起來像是關係的示意圖。
例如,要將最多 100 人與其所屬公司配對:
MATCH (p:Person)-[:workAt]->(c:Company)
RETURN p.firstName, p.lastName, c.name
LIMIT 100
當你不知道或不在意方向時,可以用無向邊緣圖案。 例如,無論誰發起連結,最多可找到100位共同熟人:
MATCH (a:Person)-[:knows]-(b:Person)
RETURN a.firstName, b.firstName
LIMIT 100
Note
Graph 目前不支援建立無向邊,但你可以用 -[:label]- 語法查詢任意方向的邊。
帶有內聯 WHERE 的過濾模式
當條件定義了哪個節點或邊可參與比對時,請將 WHERE 放在模式內。 使用陳述層級的條件 MATCH ... WHERE,對已完成的比對結果進行後置篩選;如果條件適用於較早陳述所產生的資料列,則使用另一個獨立的 FILTER。 謂詞的擺放可能會改變最短路徑的結果。 欲了解更多資訊,請參閱 「路徑選擇前或後的條件置換」。
例如,要找到1990年前出生,且在名稱以「A」開頭的公司工作的人:
MATCH (p:Person WHERE p.birthday < 19900101)-[:workAt]->(c:Company WHERE c.name STARTS WITH 'A')
RETURN p.firstName, p.lastName, c.name
依據邊屬性過濾,以限制符合條件的關係。 例如,只申報2010年或之後開始在公司工作的人員:
MATCH (p:Person)-[w:workAt WHERE w.workFrom >= 2010]->(c:Company)
RETURN p.firstName, c.name, w.workFrom
匹配多跳關係
使用可變長度的模式在一個表達式中遍歷多個跳點。 使用 {min,max} 語法來指定最小和最大跳數。
例如,要找到多達100名能夠被聯繫的人,這些人在愛麗絲朋友互動的兩到四層級之內:
MATCH (src:Person WHERE src.firstName = 'Alice')-[:knows]->{2,4}(dst:Person)
RETURN dst.firstName, dst.lastName
LIMIT 100
要尋找從 Alice 開始最多 100 個直接和二級連結(一或兩次跳躍):
MATCH (src:Person WHERE src.firstName = 'Alice')-[:knows]->{1,2}(dst:Person)
RETURN DISTINCT dst.firstName, dst.lastName
LIMIT 100
使用路徑模式控制遍歷
預設情況下,GQL 使用 WALK,允許重複節點與邊。 需要更嚴格元素獨特性時,可以用其他路徑模式。
| 路徑模式 | 行為 | 使用時機... |
|---|---|---|
WALK |
預設允許重複節點與邊 | 你想要找出所有在有限範圍內符合條件的步行路徑。 |
TRAIL |
沒有重複的邊緣 | 你想避免重複追蹤同一條邊,但同一個節點可能會穿過不同的邊。 |
SIMPLE |
除了共用的起點和終點節點外,沒有重複節點,也沒有重複邊 | 你不希望路徑中間的節點不應重複出現,但可以允許路徑回到起點。 這對於偵測迴圈很有用。 |
ACYCLIC |
無重複節點或邊 | 你需要確保路徑上沒有任何節點出現超過一次。 用於嚴謹的階層結構、分支,或任何重複訪問節點會產生錯誤結果的遍歷。 |
WALK 是最寬鬆且 ACYCLIC 限制最嚴格的模式。
對於 SIMPLE 和 ACYCLIC,邊唯一性可由節點唯一性推導出。
SIMPLE路徑可以藉由回到第一個節點而形成封閉路徑,但仍不能重複使用同一條邊。
為了說明差異,請考慮《愛麗絲→鮑勃》→《卡蘿》→鮑勃的路徑:
- WALK — 允許這條路徑。 節點與邊可以自由重複。
- TRAIL — 允許此路徑。 Bob 出現兩次,但每次邊的關係都不同(Alice→Bob 和 Carol→Bob 是不同的邊),因此不會重複邊。
- 簡單 — 阻擋這條路。 Bob 出現不只一次,SIMPLE 只允許某節點在成為路徑的起點和終點(形成封閉路徑循環)時才可重複。 這裡愛麗絲是開始,鮑勃是終點,所以沒有例外。
- 無循環 — 阻擋這條路徑。 鮑勃在路徑上出現過不只一次。
以下範例展示了如何使用TRAIL來計算在四跳之內通往 Alice 網路中前 100 位可達成員的不同路徑數量:
MATCH TRAIL (src:Person WHERE src.firstName = 'Alice')-[:knows]->{1,4}(dst:Person)
LET personId = dst.id
RETURN personId, dst.firstName, dst.lastName, count(*) AS pathCount
GROUP BY personId, dst.firstName, dst.lastName
ORDER BY pathCount DESC
LIMIT 100
可返回 ACYCLIC 最多100名可從愛麗絲在四跳內抵達的人,且路徑上的每個人都是獨一無二的:
MATCH ACYCLIC (src:Person WHERE src.firstName = 'Alice')-[:knows]->{1,4}(dst:Person)
RETURN dst.firstName, dst.lastName
LIMIT 100
預設 REPEATABLE ELEMENTS 的匹配模式允許同一圖型中不同路徑重複使用一條邊。 當所有路徑中的每個邊綁定都必須互不相同時,請使用 DIFFERENT EDGES 或 DIFFERENT RELATIONSHIPS:
MATCH DIFFERENT EDGES
(p:Person)-[:knows]->(friend:Person),
(p)-[:knows]->(other:Person)
RETURN p.firstName, friend.firstName, other.firstName
LIMIT 100
回傳一條最短路徑
ALL 是預設路徑搜尋,並回傳所有匹配的路徑。 使用 ANY SHORTEST 來回傳每對來源-目的地的最短路徑。 以下查詢可找到從愛麗絲到鮑勃的最短路徑:
MATCH p = ANY SHORTEST
(src:Person WHERE src.firstName = 'Alice')-[:knows]->{1,4}
(dst:Person WHERE dst.firstName = 'Bob')
RETURN p, path_length(p) AS hopCount
當多個最短路徑相符時,回傳的路徑並非確定性。
ALL SHORTEST 和 ANY 路徑搜尋不受支援。
謂詞的位置可能會改變 ANY SHORTEST 的結果。 內嵌節點與邊謂詞會限制哪些路徑符合資格,而後置濾波器則可以移除所選路徑,而不必選擇較長的路徑。 請參見 路徑選擇前或後的地點謂詞。
Tip
建議採用查詢成本的有限上限,以確保查詢成本可預測。 無界 ALL WALK 圖案不被支援。 帶有 TRAIL、SIMPLE 或 ACYCLIC 的無界模式會因元素唯一性而終止,但仍可能返回許多路徑。 Unbounded ANY SHORTEST WALK 只支援特定的查詢形狀。 請參見 目前的限制。
利用變數的重複使用來表達共享對象
在模式的兩個部分重複使用同一變數會產生隱含的等號限制——兩個參考必須匹配於同一個節點。 這個技巧讓你能表達「透過共享的第三實體尋找連結的實體」。
例如,要找到最多100對彼此認識且在同一家公司工作的人的步驟如下:
MATCH (c:Company)<-[:workAt]-(a:Person)-[:knows]-(b:Person)-[:workAt]->(c)
RETURN a.firstName, b.firstName, c.name
LIMIT 100
變數 c 會重複用於兩個 workAt 目標,因此查詢只會回傳雙方彼此認識 且 在同一家公司工作的配對。
要找到多達100對同時按讚同一貼文的人:
MATCH (a:Person)-[:likes]->(post:Post)<-[:likes]-(b:Person)
WHERE a.id < b.id
RETURN a.firstName, b.firstName, post.id
LIMIT 100
Tip
此 WHERE a.id < b.id 條件防止重複配對(Alice + Bob 與 Bob + Alice)出現在結果中。
結合多種圖案
在一個 MATCH中列出多個模式,中間用逗號分隔。 當模式必須綁定相同的圖形元素時,請重用變數。
例如,要找到最多100人及其工作地點及居住城市:
MATCH (p:Person)-[:workAt]->(c:Company),
(p)-[:isLocatedIn]->(city:City)
RETURN p.firstName, c.name AS company, city.name AS city
LIMIT 100
共享變數 p 連接了這兩個模式。 每一列結果代表一個人及其公司和城市。
不連通的模式同樣有效,但它們會形成其匹配結果的笛卡兒積。 只有在你有意需要所有組合時才使用。 效能指引請參見 「使用共享變數以促進高效連接」。
配對可選關係
若每個節點不一定都存在關係,請使用 OPTIONAL MATCH。 沒有匹配的行會保留 NULL 的值,這類似於 SQL 的 LEFT JOIN。
例如,回傳最多100個人,並顯示他們的公司名稱,其中包括那些公司欄位顯示NULL的無雇主者:
MATCH (p:Person)
OPTIONAL MATCH (p)-[:workAt]->(c:Company)
RETURN p.firstName, p.lastName, c.name AS company
LIMIT 100
使用 IS NULL After OPTIONAL MATCH 可以找到最多 100 位不在任何公司工作的員工:
MATCH (p:Person)
OPTIONAL MATCH (p)-[:workAt]->(c:Company)
FILTER c IS NULL
RETURN p.firstName, p.lastName
LIMIT 100