Microsoft Fabric 圖形的 GQL 語言指南

GQL(圖查詢語言)是ISO標準化的圖形資料庫查詢語言。 使用 GQL 在 Microsoft Fabric 中以圖形系統有效率地查詢、分析並處理圖形資料。

同一個標準化 SQL 的 ISO 工作小組也開發了 GQL。 因此,GQL 與 SQL 共享許多概念,包括表達式、謂詞與資料型別。 如果你有 SQL 經驗,很多知識可以應用到 GQL。

本文為圖形中GQL的端到端指南。 它說明語言如何相互銜接,並連結到專注的參考文獻以提供完整的語法和型別細節。 內容涵蓋:

  • 核心概念:圖資料結構、模式與查詢基礎
  • 基本陳述:MATCH、、FILTER、 WHENLETORDER BYLIMITRETURN
  • 資料型態與表達式:值型態、運算子與內建函式
  • 進階技術:多語句組合、變數範圍與彙整策略

備註

GQL 的官方國際標準是 ISO/IEC 39075 資訊科技 - 資料庫語言 - GQL。

如果你想要的是任務導向的指導,而非語言攻略,請參考操作指南:

當你需要完整細節時,請使用專注參考文章:

所需的資訊 權威文章
語法一覽 GQL 快速參考
節點、邊、路徑與模式組合語法 GQL 圖形模式
運算子、謂詞與函數 GQL 表達式、謂詞與函式
字面語法、值行為與型別轉換 GQL 值和值類型
圖型別定義與約束 GQL 圖表類型
目前 ISO GQL 功能涵蓋範圍 GQL 標準符合性
目前 Fabric 專屬限制與規範 目前限制

先決條件

在開始之前,請確保你熟悉以下概念:

  • 資料庫 - 具備任何資料庫系統的經驗,如關聯式(SQL)、NoSQL或圖,皆有幫助。
  • 圖概念 ——理解連接資料中的節點、邊與關係。
  • 查詢基礎 ——了解篩選、排序和聚合等基本查詢概念。

推薦背景:

  • 有 SQL 或 openCypher 語言的經驗會讓學習 GQL 語法更容易(這是 GQL 的根源)。
  • 熟悉資料建模有助於圖結構設計。
  • 了解你對圖形資料的特定使用情境。

你需要什麼:

  • 存取具備查詢功能的圖形工作空間。
  • 範例數據或願意與我們的社群網路合作範例。
  • 用於撰寫查詢的基本文字編輯器。

小提示

如果您是圖形資料庫的新手,請先從 圖形資料模型概觀 開始,再繼續本指南。

GQL 有何特別之處

GQL 專為圖形資料設計,因此其語法直接表達實體之間的連結方式。 SQL 通常透過資料表間的連接來表達關係,而 GQL 則使用類似資料圖的圖形模式。

例如,以下查詢會找到彼此認識且皆出生於1999年之前的人對:

MATCH (person:Person)-[:knows]-(friend:Person)
WHERE person.birthday < 19990101
  AND friend.birthday < 19990101
RETURN person.firstName || ' ' || person.lastName AS person_name,
       friend.firstName || ' ' || friend.lastName AS friend_name

這個模式 (person:Person)-[:knows]-(friend:Person) 顯示了相符的關係結構。 變數會綁定兩個人,讓查詢能過濾並回傳他們的屬性。

GQL 基本概念

這些概念構成了GQL的基礎:

  • 圖 包含帶有標籤和屬性的節點與邊。
  • 圖類型 正式定義了圖中允許的節點類型、邊類型及限制條件。
  • 查詢 使用如 MATCH、 FILTER、 RETURN 等陳述來處理資料並產生結果。
  • 模式 描述相符的圖結構。
  • 運算式會 計算、轉換並比較數值。
  • 謂詞 是用來測試條件的布林表達式。
  • 值型別 定義了查詢可處理的值類型及圖屬性可儲存的值類型。

了解圖表資料

要使用 GQL,你需要了解該語言查詢的標記屬性圖結構。

節點和邊緣:建構區塊

一個標記屬性圖包含兩種圖元素:

  • 節點 通常代表實體,例如人員、組織、貼文或產品。
  • 邊 代表節點間的連結,例如某人認識另一個人或在公司工作。

每個圖元素都有內部單位、一個或多個標籤,以及一組屬性。 標籤用來分類元素,例如 Person 或 knows。 屬性是名值對,例如 firstName: 'Alice' 或 birthday: 19730108u。 在圖中,一條邊總是只有一個標籤。

每條邊恰好連接兩個節點:一個原點與一個目標節點。 邊的方向是圖結構的一部分。 例如,一條workAt邊可以將原點連接到PersonCompany目標。

備註

Graph 目前不支援建立無向邊。 你可以使用任意有向邊模式(例如 -[:knows]-)。 來查詢現有的有向邊,無論向哪個方向。

圖是良構的:每條邊連接同圖中存在的兩個節點。

圖形模型和圖形類型

Fabric 圖模型定義了圖中可用的節點類型、邊類型、屬性、來源映射及鍵值。 它指定哪些來源資料表列會變成節點和邊,以及這些元素如何連接。 關於建模指導,請參見 「設計圖結構」。

GQL 標準使用 圖型 態來正式描述允許的節點類型、邊型、屬性與約束。 圖型別是 Fabric 圖模型所表示結構的語言層級對應物,但 Graph 目前並未直接接受 GQL 圖型宣告。 關於正式語法與概念,請參見 GQL 圖類型。

本指南中使用的範例圖表

範例使用 社群網路範例資料集,包含人物、地點、組織、訊息、標籤及連接它們的邊緣。

範例圖連接了以下區域:

  • 人們認識其他人,在公司工作,也在大學就讀。
  • 城市、國家或地區,以及大陸構成一個地理階層。
  • 論壇裡有貼文,人們也會發文和留言。
  • 標籤用來分類內容並代表人們的興趣。

顯示社交網路結構描述的圖表。

完整的範例結構請參見 社交網路結構範例。 關於一般的圖概念,請參見有標籤性質圖。

您的第一個 GQL 查詢

現在您已經了解了圖形基礎知識,讓我們看看如何使用 GQL 查詢圖形資料。 這些範例從簡單到複雜構建,向您展示 GQL 的方法如何使圖形查詢變得直觀且強大。

從簡單開始:找到所有人

從最基本的問題開始。 找出圖中所有人物:Person的名字(名字、姓氏)。

MATCH (p:Person)
RETURN p.firstName, p.lastName

此查詢流程如下:

  1. MATCH 找到所有標記為 Person的節點。
  2. RETURN 顯示他們的名字和姓氏。

新增篩選:尋找特定人員

現在找有特定特徵的人。 在這種情況下,找到所有叫 Alice 的人,並顯示他們的名字和生日。

MATCH (p:Person)
FILTER p.firstName = 'Alice'
RETURN p.firstName, p.lastName, p.birthday

此查詢流程如下:

  1. MATCH 找到所有標記為 Person 的節點 (p)。
  2. FILTER 節點(p),其名字是 Alice。
  3. RETURN 顯示他們的名字、姓氏和生日。

基本查詢結構

基本 GQL 查詢都遵循一致的模式:一系列語句,這些陳述式協同工作以尋找、篩選和傳回資料。 大多數查詢從尋找圖中的模式開始 MATCH ,最後以 RETURN 指定輸出結束。

這裡有一個簡單的查詢,可以找到彼此認識且同一生日的人配對,然後回傳這些朋友配對的總數。

MATCH (n:Person)-[:knows]-(m:Person)
FILTER n.birthday = m.birthday
RETURN count(*) AS same_age_friends

此查詢流程如下:

  1. MATCH 找到所有彼此認識的節點對 Person 。
  2. FILTER 只保留兩人生日相同的配對。
  3. RETURN 數數存在多少對這樣的朋友。

小提示

你也可以直接在模式中加入 WHERE 子句來過濾。 例如,只 MATCH (n:Person WHERE n.birthday < 19900101)Person 匹配 1990 年之前的節點 birthday 。

GQL支援C樣 // 式行註解、SQL樣式 -- 行註解和C樣 /* */ 式區塊註解。

常見陳述

  • MATCH: 識別要搜尋的圖型態——這裡是你定義你感興趣資料結構的地方。
  • LET:根據匹配資料指派新變數或計算值——將導出欄位加入結果。
  • FOR:將列表展開為列,並可選擇以零為基礎的偏移量或以一為基礎的序數位置。
  • CALL: 為每個輸入列執行內嵌子查詢,並加入該子查詢回傳的欄位。
  • FILTER:透過套用條件縮小結果範圍——移除不符合條件的列。
  • ORDER BY:篩選後的資料排序——根據一個或多個欄位協助組織輸出。
  • OFFSET 以及 LIMIT:限制回傳的列數——對分頁或頂尖查詢非常有用。
  • RETURN: 指定最終輸出——定義應包含哪些資料於結果集中,並執行彙總。
  • NEXT:開始另一個查詢階段,使用前一階段回傳的欄位。

陳述式如何協同運作

GQL 語句形成一條管線,每個語句處理前一個語句的輸出。 這種序列執行使查詢易於閱讀與除錯,因為執行順序與讀取順序相符。

重點︰

  • 語句實際上是依序執行的。
  • 每個語句都會轉換資料並將它傳遞給下一個。
  • 此過程創造出清晰且可預測的資料流程,簡化複雜的查詢。
  • NEXT 開始新的查詢階段。 下一階段僅可用前述陳述所投影 RETURN 的欄位。
  • UNION UNION DISTINCT、 、 並UNION ALL合併完整查詢區塊的結果。

備註

陳述句有明確的邏輯順序。 根據這些資料流撰寫查詢,而非依賴特定的物理執行策略。

陳述組成範例

以下 GQL 查詢會找到前 10 位在公司名稱中帶有「Air」字樣的公司員工,依全名排序,並回傳他們的全名及公司名稱。

-- Data flows: Match → Let → Filter → Order → Limit → Return
MATCH (p:Person)-[:workAt]->(c:Company)           -- Input: unit table, Output: (p, c) table
LET fullName = p.firstName || ' ' || p.lastName   -- Input: (p, c) table, Output: (p, c, fullName) table
FILTER c.name CONTAINS 'Air'                      -- Input: (p, c, fullName) table, Output: filtered table
ORDER BY fullName                                 -- Input: filtered table, Output: sorted table
LIMIT 10                                          -- Input: sorted table, Output: top 10 rows table
RETURN fullName, c.name AS companyName            -- Input: top 10 rows table
                                                  -- Output: projected (fullName, companyName) result table

此查詢流程如下:

  1. MATCH 找到在公司工作的人。
  2. LET 透過結合名字與姓氏來創造全名。
  3. FILTER 只保留公司名稱中帶有「Air」字樣的公司員工。
  4. ORDER BY 依全名排序。
  5. LIMIT 先取前10個結果。
  6. RETURN 回傳全名及公司名稱。

變數連接您的資料

變數,如 p、 c,在 fullName 前述範例中,會在語句間傳遞資料。 當您重複使用變數名稱時,GQL 會自動確保它引用相同的數據,從而建立強大的聯結條件。 變數有時也稱為繫結變數。

你可以用不同方式分類變數:

依綁定來源:

  • 模式變數 - 由相符的圖形模式所束縛
  • 常規變數 - 受其他語言結構約束

模式變數類型:

  • 元素變數 - 繫結至圖形元素參考值
    • 節點變數 - 繫結至個別節點
    • 邊緣變數 - 繫結至個別邊緣
  • 路徑變數 - 繫結至代表相符路徑的路徑值

按參考程度:

  • 單一變數 - 從型樣繫結至個別元素參考值
  • 群組變數 - 綁定到可變長度模式中的元素參考值清單。 詳情請參見 聚合函數。

執行結果和結果

當您執行查詢時,您會傳回包含下列內容的 執行結果 :

  • 一個結果,通常是包含你 RETURN 語句資料的結果表。
  • 顯示查詢是否成功狀態的資訊。

結果表格

結果表格 (如果存在) 是查詢執行的實際結果。

結果表格包括其直欄的名稱和類型、用來顯示結果的慣用直欄名稱序列、表格是否排序, 以及實際列本身的相關資訊。

備註

若執行失敗,執行結果中不會包含任何結果表。

省略的結果

GQL 也為那些從未產生列的語句定義了省略結果,這些陳述與資料或評估結果無關。 遺漏結果的成功完成狀態代碼 00001為 。

省略結果與空結果表不同。 空資料表表示已評估產生列的查詢,但未產生任何列。 查詢 API 可以表示遺漏結果,結果類型 NOTHING為 。

圖會保留遺漏結果,供未來的資料定義語言(DDL)及資料操作語言(DML)陳述式支援使用。 目前的查詢語句會產生資料表結果,包括空資料表。

狀態資訊

在查詢執行過程中,程序會偵測各種值得注意的狀況,例如錯誤或警告。 每個條件由執行結果的狀態資訊中的狀態物件記錄。

狀態資訊包含一個主要狀態物件及一個(可能為空的)其他狀態物件清單。 主要狀態物件始終存在,並指示查詢執行是否成功。

每個狀態物件都包含一個五字元的字母數字代碼及記錄狀況的描述。

查詢 API 使用以下主要狀態碼:

API 狀態碼 Meaning
00000 成功完成且至少有一排。
00001 成功完成但結果未公布。 預留給未來的 DDL 和 DML 支援。
01000 警告或資訊性狀況。
02000 目前沒有來自產生列查詢的資料列。
42000 一個使用者可修正的查詢錯誤。
50000 系統或非機密錯誤。

API 會保留查詢引擎 _graphaneGqlStatus 在診斷記錄成員中報告的典型 GQLSTATUS。 例如,數值溢位使用典範的 GQLSTATUS 22003,而除以零則使用 22012;兩者在公共status.code欄位中皆表示42000。

這很重要

在應用程式程式碼中,用於 status.code 廣泛成功與錯誤處理。 當你需要區分特定查詢條件時,可以使用典型的 GQLSTATUS 診斷工具。 不要測試描述文字,因為它可能會有所不同。

此外,狀態物件可以包含底層的原因狀態物件,以及帶有進一步描述記錄狀況的診斷紀錄。

基本概念和陳述

本節涵蓋撰寫有效 GQL 查詢所需的核心建置區塊。 每個概念都建立為實用的查詢寫作技能。

圖譜模式:尋找結構

圖譜模式描述了要匹配的節點、邊和路徑。 當後續陳述句需要參考匹配元素時,綁定變數:

MATCH (person:Person)-[employment:workAt]->(company:Company)
RETURN person.firstName, company.name, employment.workFrom

當謂詞定義哪個節點或邊可以參與模式時,將謂詞置於內聯:

MATCH (person:Person WHERE person.firstName = 'Alice')
      -[:knows]->(friend:Person)
RETURN friend.firstName, friend.lastName

重複使用變數,要求兩個模式位置綁定同一元素。 用逗號分開模式,組成較大的圖結構。 使用量詞 {1,4} ,例如重複邊形圖案,並匹配可變長度的路徑。

路徑模式控制元件在路徑內的重複使用:

路徑模式 行為
WALK 允許重複節點和邊。 此模式是預設模式。
TRAIL 防止重複邊緣。
SIMPLE 防止重複節點,除非共用的第一和最後一個節點。
ACYCLIC 防止所有重複的節點。

路徑搜尋前綴控制回傳哪些匹配路徑。 ALL 是預設值。 ANY SHORTEST 為每個來源-目的節點回傳一條最短路徑:

MATCH path = ANY SHORTEST
  (source:Person WHERE source.id = 123u)-[:knows]->{1,4}(target:Person)
RETURN target.id, path_length(path) AS hopCount

內線謂詞在選擇路徑前會限制路徑資格。 語句層級 MATCH ... WHERE 及之後 FILTER 的操作稱為後過濾器。 這種區分可能會改變 ANY SHORTEST 結果。

關於明確的節點、邊、路徑、組合、量詞及謂詞-擺放語意,請參見 GQL 圖模式。 關於目前路徑限制,請參見「當前限制」。

核心陳述

GQL 提供特定的語句類型,這些陳述式類型可以協同工作,逐步處理您的圖形資料。 理解這些陳述對於建立有效的查詢至關重要。

MATCH 陳述

Syntax:

MATCH <graph pattern>, <graph pattern>, ... [ WHERE <predicate> ]

該 MATCH 陳述會接收輸入資料並尋找圖形模式。 它將輸入變數與模式變數連接,輸出則全部為匹配的組合。

輸入和輸出變數:

-- Input: unit table (no columns, one row)
-- Pattern variables: p, c  
-- Output: table with (p, c) columns for each person-company match
MATCH (p:Person)-[:workAt]->(c:Company)

使用WHERE進行語句層級過濾:

-- Filter pattern matches
MATCH (p:Person)-[:workAt]->(c:Company) WHERE p.lastName = c.name

你可以用 WHERE後過濾所有匹配。 這種方法避免了獨立 FILTER 陳述。 使用路徑 ANY SHORTEST搜尋前綴如 ,則在路徑選擇後,語句層 WHERE 級會適用。 內線謂詞則限制哪些路徑有資格被選取。 欲了解更多資訊,請參閱 「路徑選擇前或後的條件置換」。

透過輸入變數連接:

當不是第一個陳述式時 MATCH ,它會將輸入資料與模式比對結合:

...
-- Input: table with 'targetCompany' column
-- Implicit join: targetCompany (equality join)
-- Output: table with (targetCompany, p, r) columns
MATCH (p:Person)-[r:workAt]->(targetCompany)

這很重要

圖支援基本及完整線性陳述組合,包括 NEXT。 你也可以將查詢 UNION區塊與 、 UNION DISTINCT、 UNION ALL、 合併。 EXCEPT、 INTERSECT和 OTHERWISE 集合運算尚未被支援。 欲了解更多資訊,請參閱關於 當前限制的文章。

關鍵加入行為:

如何 MATCH 處理資料聯結:

  • 變數等式:輸入變數透過等號匹配與模式變數結合
  • 內連接:未符合模式的輸入列會被丟棄。 用於 OPTIONAL MATCH 左外連接行為。
  • 過濾順序:模式匹配與路徑選擇完成後的語句層 WHERE 級篩選
  • 模式組成:共享變數限制模式在同一元素內。 不連通的圖案形成笛卡兒積。

這很重要

不連通的圖案是有效的,但其笛卡兒積可以產生許多行。 當模式應指向相同的圖形元素時,使用共享變數。

將模式與共享變數合併:

-- Shared variable 'p' joins the two patterns
-- Output: people with both workplace and residence data
MATCH (p:Person)-[:workAt]->(c:Company), 
      (p)-[:isLocatedIn]->(city:City)

OPTIONAL MATCH 陳述

Syntax:

OPTIONAL MATCH <graph pattern> [ WHERE <predicate> ]

OPTIONAL MATCH 運作方式類似 MATCH ,但使用左外連接語意。 若模式未找到輸入列的匹配,查詢會保留該列 NULL 未匹配變數的值,而非丟棄。

Example:

-- Find all people and, if available, their workplace
MATCH (p:Person)
OPTIONAL MATCH (p)-[:workAt]->(c:Company)
RETURN p.firstName, p.lastName, c.name AS company_name

即使沒有在任何公司工作,結果中仍會出現 。NULLcompany_name

小提示

當你想包含可能沒有特定關聯的實體時,請使用 OPTIONAL MATCH ,類似 SQL LEFT JOIN的 。

LET 陳述

Syntax:

LET <variable> = <expression>, <variable> = <expression>, ...

此 LET 陳述式會建立計算變數,並在查詢管線內啟用資料轉換。

基本變數建立:

MATCH (p:Person)
LET fullName = p.firstName || ' ' || p.lastName
RETURN *
LIMIT 1000

複雜的計算:

MATCH (p:Person)
LET adjustedAge = 2000 - (p.birthday / 10000),
    fullProfile = p.firstName || ' ' || p.lastName || ' (' || p.gender || ')'
RETURN *
LIMIT 1000

關鍵行為:

  • 查詢引擎會對每個輸入列進行運算式評估。
  • 結果會成為輸出表中的新欄位。
  • 變數只能參考先前陳述中已有的變數。
  • 一個 LET 語句中的多個指派會使用相同的輸入範圍,因此一個指派無法從該語句中引用另一個指派。

FOR 陳述

Syntax:

FOR <variable> IN <list_expression>
  [ WITH OFFSET <offset_variable> | WITH ORDINALITY <ordinality_variable> ]

該 FOR 陳述式會將清單展開成多列。 對於每個輸入列,它會為每個列表元素輸出一列,並將該元素綁定到指定的變數。 輸入列中的其他變數仍然可用。

用 WITH OFFSET 來綁定以零為基礎的指標,或用來 WITH ORDINALITY 綁定以一為基礎的位置。

LET cities = ['Seattle', 'London', 'Tokyo']
FOR city IN cities WITH ORDINALITY position
RETURN city, position

此查詢會為每個城市回傳一列。 這些值分別為 position1、 2、 3和 。 若將 替換 WITH ORDINALITY position 為 WITH OFFSET position,值為 0、 1、 2和 。

來源表達式必須評估為一個清單。 非列表值會導致查詢失敗。

CALL 陳述

用來 CALL 對每個輸入列執行內嵌子查詢:

CALL {
  <query statements>
  RETURN <columns>
}

已經在作用域中的變數則隱含地存在於子查詢中。 在子查詢中建立的變數中,只有其最終 RETURN 陳述式中的欄位能在子查詢之外使用。 在子查詢中建立但未回傳的變數仍保持本地狀態。

以下相關子查詢計算每位員工的雇主數量:

MATCH (p:Person)
CALL {
  MATCH (p)-[:workAt]->(company:Company)
  RETURN count(*) AS employerCount
}
RETURN p.firstName, p.lastName, employerCount
ORDER BY employerCount DESC

普通 CALL 人就像是依賴的內接。 它對子查詢回傳的每一列產生一列輸出資料。 若子查詢未回傳任何列,則對應的外排也不會回傳。 如果回傳多列,則每個子查詢列會顯示最外側的列一次。

前述 count(*) 範例總是回傳一個子查詢列,因為它使用了未分組的聚合。 因此,沒有匹配雇主的人擁有 employerCount 的 0。

作為依賴的左加入使用 OPTIONAL CALL 。 當子查詢未回傳任何列時,會保留一列外側,並將回傳的子查詢欄位設為 NULL。 當子查詢回傳多列時,會為每個子查詢列產生一列輸出資料。

MATCH (p:Person)
OPTIONAL CALL {
  MATCH (p)-[:workAt]->(company:Company)
  RETURN company.name AS companyName
}
RETURN p.firstName, p.lastName, companyName

你可以巢狀內嵌 CALL 子查詢。 巢狀子查詢可以參考其包圍的查詢範圍中的變數。

這很重要

將每個內嵌CALL實體以 結尾。RETURN 圖不支援命名的程序呼叫或明確的變數匯入清單,例如 CALL (p) { ... }。

FILTER 陳述

Syntax:

FILTER [ WHERE ] <predicate>

此 FILTER 陳述式可讓您精確控制哪些資料會透過查詢管線進行。

基本過濾:

MATCH (p:Person)
FILTER p.birthday < 19980101 AND p.gender = 'female'
RETURN *

複雜的邏輯條件:

MATCH (p:Person)
FILTER (p.gender = 'male' AND p.birthday < 19940101) 
  OR (p.gender = 'female' AND p.birthday < 19990101)
  OR p.browserUsed = 'Edge'
RETURN *

Null 感知篩選模式:

使用下列模式來安全地處理 Null 值:

  • 檢查值:p.firstName IS NOT NULL - 有名字
  • 驗證資料: p.id > 0 - 有效身分證件
  • 處理遺失的資料: NOT coalesce(p.locationIP, '10.x.x.x') STARTS WITH '10.x.x.x' - 未從本地網路連線
  • 組合條件: AND/OR 與複雜邏輯的明確 null 檢查一起使用

謹慎

請記住,涉及空值的條件會傳回 UNKNOWN,這會篩選掉這些列。 當您需要包含 Null 的邏輯時,請使用明確 IS NULL 檢查。

ORDER BY 陳述

Syntax:

ORDER BY <expression> [ ASC | DESC ] [ NULLS FIRST | NULLS LAST ],
         <expression> [ ASC | DESC ] [ NULLS FIRST | NULLS LAST ], ...

使用計算表達式進行多級排序:

MATCH (p:Person)
RETURN *
ORDER BY p.firstName DESC,               -- Primary: by first name (Z-A)
         p.birthday ASC,                 -- Secondary: by age (oldest first)
         p.id DESC                       -- Tertiary: by ID (highest first)

排序中的空值處理:

MATCH (p:Person)
RETURN p.firstName, p.birthday
ORDER BY p.birthday DESC NULLS LAST, p.firstName ASC

排序行為細節:

了解運作方式 ORDER BY :

  • 查詢引擎會評估每一列的表達式,然後結果決定列序。
  • 多個排序鍵會產生階層式排序(主排序、次排序、第三排序等)。
  • NULLS FIRST 將空值置於非空值之前。 NULLS LAST 將它們置於非零值之後。
  • 空置位置與排序方向無關。 如果你沒有指定空序,則 NULLS LAST 是 和 DESC的預設ASC值。
  • ASC (升序)是預設順序,你必須明確指定 DESC (降序)。
  • 你可以依計算出的值排序,而不只是儲存的屬性。
排序規範 結果順序
ASC 或 ASC NULLS LAST 非空值依序遞減,接著是空值。
ASC NULLS FIRST 空值,接著是非空值,依序由高到低排列。
DESC 或 DESC NULLS LAST 非空值由降序排列,接著是空值。
DESC NULLS FIRST 空值,接著是非空值,從高到低排列。

謹慎

只有 緊接 著的語句才能看到建立的排序順序 ORDER BY 。 因此, ORDER BY 接著 並 RETURN * 不會產生有序結果。

比:

MATCH (a:Person)-[r:knows]->(b:Person)
LET aName = a.firstName || ' ' || a.lastName
LET bName = b.firstName || ' ' || b.lastName
ORDER BY r.creationDate DESC
/* intermediary result _IS_ guaranteed to be ordered here */
RETURN aName, bName, r.creationDate AS since
/* final result _IS_ _NOT_ guaranteed to be ordered here  */

取代為:

MATCH (a:Person)-[r:knows]->(b:Person)
LET aName = a.firstName || ' ' || a.lastName
LET bName = b.firstName || ' ' || b.lastName
/* intermediary result _IS_ _NOT_ guaranteed to be ordered here */
RETURN aName, bName, r.creationDate AS since
ORDER BY r.creationDate DESC
/* final result _IS_ guaranteed to be ordered here              */

此差異對「Top-k」查詢有立即影響: LIMIT 必須始終跟隨 ORDER BY 建立預期排序順序的陳述。

OFFSET 和 LIMIT 語句

Syntax:

  OFFSET <offset> [ LIMIT <limit> ]
| LIMIT <limit>

常見模式:

-- Basic top-N query
MATCH (p:Person)
RETURN *
ORDER BY p.id DESC
LIMIT 10                                 -- Top 10 by ID

這很重要

如需可預測的分頁結果,請一律使用 ORDER BY before OFFSET 和 LIMIT 以確保查詢之間的資料列順序一致。

RETURN:基本結果預測

Syntax:

RETURN [ DISTINCT ] <expression> [ AS <alias> ], <expression> [ AS <alias> ], ...
[ ORDER BY <expression> [ ASC | DESC ] [ NULLS FIRST | NULLS LAST ], ... ]
[ OFFSET <offset> ]
[ LIMIT <limit> ]

此 RETURN 陳述式會指定結果資料表中顯示哪些資料,以產生查詢的最終輸出。

基本輸出:

MATCH (p:Person)-[:workAt]->(c:Company)
RETURN p.firstName || ' ' || p.lastName AS name, 
       p.birthday, 
       c.name

為了清楚起見,使用別名:

MATCH (p:Person)-[:workAt]->(c:Company)
RETURN p.firstName AS first_name, 
       p.lastName AS last_name,
       c.name AS company_name

結合排序和top-k:

MATCH (p:Person)-[:workAt]->(c:Company)
RETURN p.firstName || ' ' || p.lastName AS name, 
       p.birthday AS birth_year, 
       c.name AS company
ORDER BY birth_year ASC
LIMIT 10

使用 DISTINCT 進行重複處理:

-- Remove duplicate combinations
MATCH (p:Person)-[:workAt]->(c:Company)
RETURN DISTINCT p.gender, p.browserUsed, p.birthday AS birth_year
ORDER BY p.gender, p.browserUsed, birth_year

結合彙總:

MATCH (p:Person)-[:workAt]->(c:Company)
RETURN count(DISTINCT p) AS employee_count

RETURN with GROUP BY:分組結果投影

Syntax:

RETURN [ DISTINCT ] <expression> [ AS <alias> ], <expression> [ AS <alias> ], ...
GROUP BY <variable>, <variable>, ...
[ ORDER BY <expression> [ ASC | DESC ], <expression> [ ASC | DESC ], ... ]
[ OFFSET <offset> ]
[ LIMIT <limit> ]

用 GROUP BY 來依共用值將資料列分組,並在每個群組內計算彙總函數。

具有彙總的基本分組:

MATCH (p:Person)-[:workAt]->(c:Company)
LET companyId = c.id, companyName = c.name
RETURN companyId,
       companyName,
       count(*) AS employeeCount,
       avg(p.birthday) AS avg_birth_year
GROUP BY companyId, companyName
ORDER BY employeeCount DESC

多欄分組:

MATCH (p:Person)
LET gender = p.gender
LET browser = p.browserUsed
RETURN gender,
       browser,
       count(*) AS person_count,
       avg(p.birthday) AS avg_birth_year,
       min(p.creationDate) AS first_joined,
       max(p.id) AS highest_id
GROUP BY gender, browser
ORDER BY avg_birth_year DESC
LIMIT 10

備註

關於可變長度模式的水平聚合,請參見 聚合函數。

值和值類型

GQL 值包括布林值、字串值、數字值、時間值、列表值、節點值、邊值、路徑值、空值及無值值。 型別是可空的,除非你指定 NOT NULL。 屬性使用完整查詢值系統中支援的子集。

RETURN 42 AS integerValue,
       'Alice' AS stringValue,
       TRUE AS booleanValue,
       [1, 2, 3] AS listValue

與虛無的比較評估為UNKNOWN;用於IS NULLIS NOT NULL虛無檢定。 數值運算可以在相容的數值類型間進行隱式轉換。

備註

並非所有 GQL 值類型在每個圖譜上下文中都被支援。 關於目前屬性與查詢限制,請參見 資料型別。

關於字面語法、比較行為、型別轉換及型別階層,請參見 GQL 值與值型別。

Expressions

表達式會計算、比較、彙總並轉換數值。 常見的形式包括屬性參照、算術與邏輯運算子、謂詞、函式呼叫、簡單 CASE 表達式及子查詢:

MATCH (person:Person)
FILTER person.birthday < 19900101
RETURN person.firstName,
       CASE person.gender
         WHEN 'female' THEN 'F'
         WHEN 'male' THEN 'M'
         ELSE 'Other'
       END AS genderCode

GQL 使用三值邏輯:布林表達式可以評估為 TRUE、 FALSE、 或 UNKNOWN。 A FILTER 只保留其謂詞為 TRUE的列。

彙總函數如 COUNT、 SUM、 AVG、 MIN、 及 MAX 彙整列數。 列表謂詞如 ALL、 ANY、 NONE,並 SINGLE 對列表元素評估謂詞。 程序表單 EXISTS 子查詢測試巢狀查詢是否回傳一列。

關於完整的運算子、謂詞、聚合與函數行為,請參見 GQL 表達式、謂詞與函數。 關於任務導向的過濾與分組範例,請參見 「篩選與聚合圖資料」。

進階查詢技術

本節介紹用於建立複雜、高效的圖形查詢的複雜模式和技術。 這些模式超越基本陳述式用法,可協助您撰寫強大的分析查詢。

複多語句組合

這很重要

圖支援基本及完整線性陳述組合。 EXCEPT、 INTERSECT和 OTHERWISE 集合運算尚未被支援。 欲了解更多資訊,請參閱關於 當前限制的文章。

了解如何有效地撰寫複雜的查詢對於進階圖形查詢至關重要。

UNION 與 UNION ALL

使用 UNION、 UNION DISTINCT或 來 UNION ALL 結合兩個或以上線性查詢區塊的結果:

<query block>
UNION [ DISTINCT | ALL ]
<query block>
-- Combine results from two separate pattern matches
MATCH (p:Person)-[:workAt]->(c:Company)
RETURN p.firstName AS name, c.name AS affiliation
UNION DISTINCT
MATCH (p:Person)-[:studyAt]->(u:University)
RETURN p.firstName AS name, u.name AS affiliation

Bare UNION 等同於 UNION DISTINCT;兩者都會移除重複的行。 UNION ALL 保留所有列,包括重複的列。

每個查詢區塊必須回傳相同的欄位名稱集合。 欄位順序可能因區塊而異,且資料型態必須相容。

NEXT

用 NEXT 來對前一階段返回的資料表執行另一個查詢階段:

<query stage>
RETURN <columns>
NEXT
<query stage>

以下查詢會找到員工及其公司,然後利用回傳的員工節點進行另一個模式匹配:

MATCH (person:Person)-[:workAt]->(company:Company)
RETURN person, company.name AS companyName
NEXT
MATCH (person)-[:isLocatedIn]->(city:City)
RETURN person.firstName AS employee, companyName, city.name AS city

只有前一階段回傳的欄位才在 之後 NEXT的範圍內。 你可以使用多個 NEXT 分隔符來建立更長的查詢階段序列。

任一階段都可以包含查詢區塊的聯集。 在該階段的輸出越過 NEXT 邊界之前,會先在其階段內評估聯合。 若 A、 、 代表C查詢區塊,A UNION B NEXT C分組為 (A UNION B) NEXT C,而A NEXT B UNION C分組為 A NEXT (B UNION C)B。

條件陳述式

使用條件語句將每個輸入的列路由到第一個分支,其謂詞值為 TRUE:

WHEN <predicate> THEN <linear query statement or { query statements }>
[ WHEN <predicate> THEN <linear query statement or { query statements }> ... ]
[ ELSE <linear query statement or { query statements }> ]

要路由前一查詢階段的列,回傳所需的欄位,並在條件語句前使用 NEXT :

MATCH (p:Person)
RETURN p.firstName AS name, p.birthday AS birthday
NEXT
WHEN birthday < 19800101u THEN
  RETURN name, 'Before 1980' AS era
WHEN birthday < 20000101u THEN
  RETURN name, '1980-1999' AS era
ELSE
  RETURN name, '2000 or later' AS era

每個 WHEN 謂詞必須是布林值。 查詢引擎會依序評估每個輸入列的謂詞。 一個條件,評估或FALSEUNKNOWN不選擇其分支。 當謂詞評估到 TRUE後,之後的謂詞和未被選取的分支體則不再被評估。 如果沒有謂詞能應值到 且 TRUE 沒有 ELSE,則輸入列不會回傳。

謂詞與分支實體可參考前一階段的欄位。 分支可以是單一線性陳述,也可以是包裹在大括號中的巢狀程序。 當一個分支需要多個階段或多個陳述式時,使用巢狀程序,例如 CALL:

MATCH (p:Person)
RETURN p, p.firstName AS name
NEXT
WHEN p.gender = 'female' THEN {
  CALL {
    MATCH (p)-[:knows]->(friend:Person)
    RETURN count(*) AS friendCount
  }
  RETURN name, friendCount
}
ELSE
  RETURN name, 0u AS friendCount

每個分支都有自己的地方範圍。 兄弟分支不會看到其他分支所建立的變數,只有所選分支 RETURN 最後的欄位在條件陳述後繼續。 每個分支必須回傳相同的欄位名稱,且對應的結果類型必須相容。 查詢引擎會強制相容型別到共同的輸出型態。 回傳的分支欄位可與輸入欄位使用相同名稱;分支值取代條件輸出中的輸入值。

條件語句與 CASE 表達式不同。 圖譜支援簡單的 CASE <expression> WHEN <value>,但不搜尋 CASE WHEN <predicate> 的表達式。 欲了解更多資訊,請參閱 條件表達式。

可變範圍和進階流量控制

變數跨查詢語句連接資料並啟用複雜的圖形遍歷。 瞭解進階範圍規則可協助您撰寫複雜的多語句查詢。

變數綁定與範圍模式

-- Variables flow forward through subsequent statements 
MATCH (p:Person)                                    -- Bind p 
LET fullName = p.firstName || ' ' || p.lastName     -- Bind concatenation of p.firstName and p.lastName as fullName
FILTER fullName CONTAINS 'Smith'                    -- Filter for fullNames with “Smith” substring (p is still bound)
RETURN p.id, fullName                               -- Only return p.id and fullName (p is dropped from scope) 

跨敘述的連接時的變數重用

-- Multi-statement joins using variable reuse
MATCH (p:Person)-[:workAt]->(:Company)          -- Find people with jobs
MATCH (p)-[:isLocatedIn]->(:City)               -- Same p: people with both job and residence
MATCH (p)-[:knows]->(friend:Person)             -- Same p: their social connections
RETURN *

關鍵範疇規則與限制

-- ✅ Backward references work
MATCH (p:Person)
LET adult = p.birthday < 20061231  -- Can reference p from previous statement
RETURN *

-- ❌ Forward references don't work  
LET adult = p.birthday < 20061231  -- Error: p not yet defined
MATCH (p:Person)
RETURN *

-- ❌ Variables in same LET statement can't reference each other
MATCH (p:Person)
LET name = p.firstName || ' ' || p.lastName,
    greeting = 'Hello, ' || name     -- Error: name not visible yet
RETURN *

-- ✅ Use separate statements for dependent variables
MATCH (p:Person)
LET name = p.firstName || ' ' || p.lastName
LET greeting = 'Hello, ' || name     -- Works: name now available
RETURN *

複雜查詢中的變量可見性

-- Variables remain visible until overridden or query ends
MATCH (p:Person)                     -- p available from here
LET gender = p.gender                -- gender available from here  
MATCH (p)-[:knows]->(e:Person)       -- p still refers to original person
                                     -- e is a new variable for the friend
RETURN p.firstName AS manager, e.firstName AS friend, gender

謹慎

同一語句中的變數不能互相參照,除非在圖模式中。 使用單獨的陳述式來建立應變數。

聚合列與路徑元素

GQL 支援兩種聚合上下文:

  • 垂直聚合 是將輸入列彙總,並可選擇依 GROUP BY 變數劃分。
  • 水平聚合 總結了一個由可變長度邊型圖樣所界定的群組列表,該群組在一條匹配路徑內。
MATCH (person:Person)-[:workAt]->(company:Company)
LET companyId = company.id, companyName = company.name
RETURN companyId, companyName, count(*) AS employeeCount
GROUP BY companyId, companyName
MATCH (:Person)-[connections:knows]->{1,4}(:Person)
RETURN count(connections) AS pathLength

關於群組查詢、聚合專屬篩選器、集合聚合及條件路由,請參見 篩選與聚合圖資料。 完整的彙總結果規則,請參見 彙總函數。

處理空值與查詢錯誤

當缺失值需要明確處理時,使用明確的空測試:

MATCH (person:Person)
FILTER person.browserUsed IS NULL
RETURN person.firstName

與 null 比較時,得值為 UNKNOWN,a FILTER 不保留此值。 需要備用值時使用 coalesce() 。

查詢結果包括成功狀態資訊、警告、無資料狀況、使用者可修正錯誤及系統錯誤。 使用公開狀態碼進行廣泛的控制流程,並使用標準的 GQLSTATUS 診斷以處理特定狀況。 請參閱 執行結果與結果 ,以及 GQL 狀態碼參考資料。

保留字詞

GQL 會保留某些您無法用作識別碼的關鍵字,例如變數、屬性名稱或標籤名稱。 如需完整清單,請參閱 GQL 保留字組參考 。

如果您需要使用保留字作為標識符,請使用反引號轉義它們: `match`, `return`。

若要避免逸出保留字,請使用此命名慣例:

  • 對於單字識別碼,請附加底線: :Product_
  • 對於多字標識符,請使用駝峰命名法或帕斯卡命名法: :MyEntity, :hasAttribute, textColor

後續步驟