GQL 语言指南

注释

此功能目前处于公开预览状态。 此预览版在没有服务级别协议的情况下提供,不建议用于生产工作负荷。 某些功能可能不受支持或者受限。 有关详细信息,请参阅 Microsoft Azure 预览版补充使用条款

GQL 图形查询语言是图形数据库的 ISO 标准化查询语言。 它可帮助你高效地查询和使用图形数据。

GQL由与标准化SQL的ISO工作组共同开发,确保一致性和严谨性。 如果你熟悉 SQL,会发现 GQL 有很多相似之处(表达式、谓词、类型),这让入门更容易。 本指南为学习 GQL 基础知识的新手和寻求高级技术和综合参考信息的经验丰富的用户提供服务。

注释

GQL 的官方国际标准是 ISO/IEC 39075 信息技术 - 数据库语言 - GQL

先决条件

在深入了解 GQL 之前,应熟悉以下概念:

  • 数据库的基本了解——任何数据库系统(如关系型(SQL)、NoSQL 或图)的经验都很有帮助
  • 图形概念 - 了解连接数据中的节点、边缘和关系
  • 查询基础知识 - 了解基本查询概念,例如筛选、排序和聚合

建议的背景:

  • 有SQL或openCypher语言经验能让学习GQL语法更容易(它们是GQL的根源)。
  • 熟悉数据建模有助于进行图形架构设计
  • 了解图形数据的特定用例

需要满足以下条件:

  • 使用图形功能访问 Microsoft Fabric
  • 示例数据或愿意使用我们的社交网络示例
  • 用于编写查询的基本文本编辑器

小窍门

如果你不熟悉图形数据库,请先了解 图形数据模型概述 ,然后再继续本指南。

是什么使 GQL 特别

GQL 专为图形数据设计。 这使得处理连接信息变得自然而直观。

与依赖表连接表达关系的SQL不同,GQL使用可视化图模式,直接镜像实体之间的连接方式,使查询更易阅读和推理。

假设你想找到1999年之前出生的人和他们的朋友(彼此认识的人)。 GQL用可视化图模式表达了这一点:

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

此查询查找在 1999 年之前出生的朋友(认识彼此的人)。 该模式 (person:Person)-[:knows]-(friend:Person) 直观显示要查找的关系结构,这与绘制数据关系图非常类似。

GQL 基础知识

在深入查询之前,请了解构成 GQL 基础的以下核心概念:

  • 图将 你的数据存储为节点(实体)和边(关系),每个节点都有标签和属性
  • 图形类型 类似于架构,定义图形中可以存在的节点和边缘
  • 约束 是图类型对图施加的额外规则和限制,以强制数据完整性
  • 查询 使用语句,例如 MATCHFILTERRETURN 处理数据和显示结果
  • 模式 描述想要使用直观的视觉语法查找的图形结构
  • 表达式 对数据执行计算和比较,类似于 SQL 表达式
  • 谓词 是用于查询中过滤结果的布尔值表达式
  • 值类型 定义可以处理和存储的值类型

了解图形数据

若要有效地使用 GQL,需要了解图形数据的结构。 此基础可帮助你有效地编写更好的查询和数据建模。

节点和边缘:构建基块

在 GQL 中,可以使用标记的属性图。 图形由两种类型的元素组成:

节点 通常表示系统中的实体(“名词”),例如人员、组织、帖子或产品。 它们是域中存在的独立对象。 节点有时也称为顶点。

边缘 表示实体(“谓词”)之间的关系 -- 实体如何连接和交互。 例如,人们彼此认识(:knows)、在特定地区运营的组织(:operates)、或购买产品的客户(:purchased)。
边缘有时也称为关系。

每个图形元素都有以下特征:

  • 唯一标识它的内部 ID
  • 一个或多个标签 - 描述性名称,例如 Personknows。 在 Microsoft Fabric 中,图边总是只有一个标签。
  • 属性——存储元素数据的名值对(如 firstName: "Alice"birthday: "19730108")。

图形的结构

每个边缘完全连接两个节点:源和目标。 此连接创建图形的结构,并显示实体如何相互关联。 边缘的方向很重要— 另一Person个创建follows定向关系的人Person

注释

Microsoft Fabric中的Graph目前不支持无向边。

Microsoft Fabric 支持的属性图始终是良构的,意味着每条边连接两个有效节点。 如果在图形中看到边缘,则其两个终结点都存在于同一个图形中。

图形模型和图形类型

Microsoft Fabric 中图形的结构由其 图形模型描述,该模型类似于应用程序域的数据库架构。 图形模型定义:

  • 哪些节点和边缘可以存在
  • 他们可以拥有哪些标签和属性
  • 节点和边缘如何连接

图形模型还通过约束确保数据完整性,尤其是指定哪些属性唯一标识每个节点的 节点键约束

注释

可以使用 GQL 标准语法指定图形模型,在这种情况下,它们称为 图形类型

一个实际示例:社交网络

在整个文档中,我们使用社交网络示例来说明 GQL 概念。 了解此域有助于遵循示例,并将类似的模式应用于自己的数据。

显示社交网络架构的关系图。

注释

社交网络是从 GDC (图形数据委员会)发布的 LDBC SNB (LDBC 社交网络基准)派生的。 有关更多详细信息,请参阅文章“LDBC 社交网络基准”。

社交网络实体

我们的社交网络包括以下主要类型的节点,表示域的实体:

人们 拥有姓名、生日和性别等个人信息。 他们生活在城市,形成社会联系。

位置 构成地理层次结构:

  • “纽约”或“伦敦”等城市
  • “美国”或“英国”等国家/地区
  • “北美”或“欧洲”等大陆

人们花时间的组织

  • 人们学习的大学
  • 人员工作的公司

内容和讨论:

  • 包含帖子标题的论坛
  • 包含内容、语言和可选图像的帖子
  • 回复帖子或其他批注的批
  • 对内容进行分类和表示兴趣的标记

所有内容如何连接

实体之间的连接使网络变得有趣:

  • 人们彼此认识(友谊), :knows
  • 人们在公司工作(:workAt)或在大学学习(:studyAt
  • 人们会:hasCreator发帖和评论()
  • 人们点赞帖子和评论(:likes
  • 帖子、论坛、评论都可以带有标签(:hasTag
  • 人们对特定标签感兴趣(:hasInterest
  • 论坛包含帖子(),:containerOf并设有成员(:hasMember)和版主(:hasModerator

图形边缘表示域关系。 这种丰富的网络为有趣的查询和分析创造了许多机会。

你的第一个 GQL 查询

了解图形基础知识后,让我们了解如何使用 GQL 查询图形数据。 这些示例以简单到复杂的方式生成,展示了 GQL 的方法如何直观且强大。

开始简单:查找所有人员

让我们从最基本的查询开始,找出图中所有人物:Person的名字(名字、姓氏)。

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

该查询的执行方式如下:

  1. MATCH 查找标记的所有节点 Person
  2. RETURN 显示其名字和姓氏

添加筛选:查找特定人员

现在我们来找具有特定特征的人,在这里,所有叫Alice的人,并展示他们的名字和生日。

MATCH (p:Person)
FILTER p.firstName = 'Annemarie'
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.age > 23) 将仅匹配 Person 其属性大于 23 的 age 节点。

注释

GQL 支持 C 样式 // 行注释、SQL 样式 -- 的行注释和 C 样式 /* */ 块注释。

常见陈述

  • MATCH:识别要搜索的图型——这里是你定义你感兴趣数据结构的地方。
  • LET:根据匹配数据分配新变量或计算值——向结果添加派生列。
  • FILTER:通过应用条件缩小结果范围——删除不符合条件的行。
  • ORDER BY:对过滤数据进行排序——帮助基于一个或多个字段组织输出。
  • OFFSET 以及 LIMIT:限制返回的行数——适用于分页或顶K查询。
  • RETURN: 指定最终输出——定义应包含哪些数据并进行聚合。

语句如何协同工作

GQL 语句构成一个流水线,每个语句处理前一个语句的输出。 这种顺序执行使查询易于读取和调试,因为执行顺序与读取顺序一致。

要点:

  • 语句实际上是顺序执行的。
  • 每个语句转换数据并将其传递给下一个语句。
  • 这创造了一个清晰且可预测的数据流,简化了复杂的查询。

重要

在内部,语句的执行可以重新排序,并由 Microsoft Fabric 并行执行单个语句,以最大化性能。 但这不会影响结果的正确性。

示例

以下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 查找在公司名称中带有“Air”字样的公司工作人员
  2. LET 通过组合名字和姓氏来创建全名
  3. FILTER 仅保留Contoso员工
  4. ORDER BY 按全名排序
  5. LIMIT 取前10个结果
  6. RETURN 退货名称及公司地点

变量连接数据

变量(如 pcfullName 前面的示例中)在语句之间传递数据。 重复使用变量名称时,GQL 会自动确保它引用相同的数据,从而创建强大的联接条件。 变量有时也称为绑定变量。

变量可以采用不同的方式进行分类:

通过绑定源:

  • 模式变量 - 由匹配的图形模式绑定
  • 常规变量 - 由其他语言构造绑定

模式变量类型:

  • 元素变量 - 绑定到图形元素引用值
    • 节点变量 - 绑定到单个节点
    • 边缘变量 - 绑定到单个边缘
  • 路径变量 - 绑定到表示匹配路径的路径值

按参考度:

  • 单一实例变量 - 绑定到模式中的单个元素引用值
  • 组变量 - 绑定到可变长度模式中的元素引用值列表(请参阅 高级聚合技术

执行结果和结果

运行查询时,将返回一个由以下项组成的 执行结果

  • 一个(可选)结果表 ,其中包含语句中的数据 RETURN
  • 显示查询是否成功的状态信息

结果表

结果表(如果存在)是查询执行的实际结果。

结果表包含有关其列的名称和类型的信息、用于显示结果的首选列名称序列、表是否排序 以及实际行本身。

注释

如果执行失败,执行结果中不包含任何结果表。

状态信息

在执行查询期间会检测到各种值得注意的条件(例如错误或警告)。 每个此类条件都由执行结果的状态信息中的状态对象记录。

状态信息由主要状态对象和附加状态对象的(可能为空)列表组成。 主状态对象始终存在,并指示查询执行是成功还是失败。

每个状态对象都包含一个 5 位状态代码(称为 GQLSTATUS),用于标识记录的条件以及描述该状态的消息。

成功状态代码:

GQLSTATUS Message When
00000 注意:成功完成 至少一行成功
00001 注意:成功完成 - 省略的结果 没有表(当前未使用)成功
02000 注意:无数据 包含零行的成功

其他状态代码指示在查询执行期间检测到的进一步错误或警告。

重要

在应用程序代码中,始终依赖于状态代码来测试某些条件。 状态代码保证稳定,其常规含义将来不会更改。 不要测试消息内容,因为具体消息可能会根据查询不同,甚至在同一查询执行之间发生变化。

此外,状态对象可以包含基础原因状态对象和诊断记录,其中包含描述所记录条件的进一步信息。

基本概念和语句

本部分介绍编写有效的 GQL 查询所需的核心构建基块。 每个概念都以实际查询编写技能为基础。

图形模式:查找结构

图形模式是 GQL 查询的核心。 它们允许你描述想要使用直观的视觉语法来描述想要查找的关系的数据结构。

简单模式:

从基本关系模式开始:

-- Find direct friendships
(p:Person)-[:knows]->(f:Person)

-- Find people working at any company
(p:Person)-[:workAt]->(c:Company)

-- Find cities in any country/region
(ci:City)-[:isPartOf]->(co:Country)  

具有特定数据的模式:

-- Find who works at Microsoft specifically
(p:Person)-[:workAt]->(c:Company)
WHERE p.firstName = 'Annemarie'

-- Find friends who are both young
(p:Person)-[:knows]->(f:Person)  
WHERE p.birthday > 19950101 AND f.birthday > 19950101

灵活实体选择的标签表达式:

(:Person|Company)-[:isLocatedIn]->(p:City|Country)  -- OR with |
(:Place&City)                                       -- AND with &  
(:Person&!Company)                                  -- NOT with !

注释

多元素标签的图模型尚未被支持(已知问题)。

使用标签表达式,可以在单个模式中匹配不同类型的节点,使查询更加灵活。

变量重用可创建强大的联接:

-- Find coworkers: people who work at the same company
(c:Company)<-[:workAt]-(x:Person)-[:knows]-(y:Person)-[:workAt]->(c)

重复使用变量 c 可确保两人 在同一 家公司工作,从而创建自动联接约束。 此模式是表示“同一实体”关系的关键模式。

重要

关键见解:模式中的变量重用会创建结构约束。 这种技术是如何表达复杂的图形关系,例如“在同一家公司工作的朋友”或“同一个城市的人”。

使用 WHERE 的模式级别筛选:

-- Filter during pattern matching (more efficient)
(p:Person WHERE p.birthday < 19940101)-[:workAt]->(c:Company WHERE c.id > 1000)

-- Filter edges during matching  
(p:Person)-[w:workAt WHERE w.workFrom >= 2000]->(c:Company)

有限可变长度模式:

(:Person)-[:knows]->{1,3}(:Person)  -- Friends up to 3 degrees away

无周期遍历的 TRAIL 模式:

使用 TRAIL 模式防止在图形遍历期间循环,确保每次访问每个边缘一次:

-- Find paths without visiting the same :knows edge twice
MATCH TRAIL (src:Person)-[:knows]->{1,4}(dst:Person)
WHERE src.firstName = 'Alice' AND dst.firstName = 'Bob'
RETURN count(*) AS num_connections
-- Find acyclic paths in social networks
MATCH TRAIL (p:Person)-[e:knows]->{,3}(celebrity:Person)
RETURN 
  p.firstName || ' ' || p.lastName AS person_name, 
  celebrity.firstName || ' ' || celebrity.lastName AS celebrity_name, 
  count(e) AS distance
LIMIT 1000

可变长度边缘绑定:

在可变长度模式中,边缘变量根据上下文捕获不同的信息:

-- Edge variable 'e' binds to a single edge for each result row
MATCH (p:Person)-[e:knows]->(friend:Person)
RETURN p.firstName, e.creationDate, friend.firstName  -- e refers to one specific relationship
LIMIT 1000

-- Edge variable 'e' binds to a group list of all edges in the path
MATCH (p:Person)-[e:knows]->{2,4}(friend:Person)  
RETURN 
  p.firstName || ' ' || p.lastName AS person_name, 
  friend.firstName || ' ' || friend.lastName AS friend_name, 
  -- e is a list
  size(e) AS num_edges
LIMIT 1000

这种区别对于正确使用边缘变量至关重要。

具有多个关系的复杂模式:

MATCH (p:Person), (p)-[:workAt]->(c:Company), (p)-[:isLocatedIn]->(city:City)
RETURN p.firstName, p.lastName, c.name AS company_name, city.name AS city_name
LIMIT 1000

此模式查找人员及其工作场所和居住地,显示一个人如何连接到多个其他实体。

核心语句

GQL 提供一起处理图形数据的特定语句类型。 了解这些语句对于生成有效查询至关重要。

MATCH 语句

语法:

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 语句。

使用输入变量联接:

MATCH 不是第一个语句时,它会将输入数据与模式匹配联接:

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

重要

Microsoft Fabric 中的图形尚不支持任意语句组合。 请参阅 有关当前限制的文章。

键联接行为:

如何处理 MATCH 数据联接:

  • 变量相等性:使用相等匹配的模式变量联接输入变量
  • 内部联接:丢弃无模式匹配的输入行(左/右联接)
  • 筛选顺序:模式匹配完成后的语句级 WHERE 筛选器
  • 模式连接:多个模式必须共享至少一个变量才能正确联接
  • 性能:共享变量创建高效的联接约束

重要

限制:如果这不是 MATCH 第一个语句,则至少有一个输入变量必须与模式变量联接。 多个模式必须有一个共同的变量。

多个模式需要共享变量:

-- 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)

LET 语句

语法:

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 中的多个赋值并行计算(无交叉引用)

FILTER 语句

语法:

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 - 有效 ID
  • 处理缺失的数据NOT coalesce(p.locationIP, '127.0.0.1') STARTS WITH '127.0.0' - 未从本地网络进行连接
  • 组合条件:对复杂逻辑使用 AND/OR 显式 null 检查

注意

请记住,涉及 null 值的条件返回 UNKNOWN,这会筛选掉这些行。 需要 null 非独占逻辑时,请使用显式 IS NULL 检查。

ORDER BY 语句

语法:

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

使用计算表达式进行多级排序:

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)

排序中的 Null 处理:

ORDER BY coalesce(p.gender, 'not specified') DESC -- Treat NULL as 'not specified'

排序行为详细信息:

了解工作原理 ORDER BY

  • 表达式计算:对每行计算表达式,然后结果确定行顺序
  • 多个排序键:创建分层排序(主要、次要、第三级等)
  • Null 处理NULL 始终被视为比较中的最小值
  • 默认顺序ASC (升序)为默认值, DESC 必须显式指定(降序)
  • 计算排序:可以按计算值进行排序,而不仅仅是存储的属性

注意

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 建立预期排序顺序的语句。

OFFSETLIMIT 语句

语法:

  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使用OFFSETLIMIT并确保跨查询进行一致的行排序。

RETURN:基本结果投影

语法:

RETURN [ DISTINCT ] <expression> [ AS <alias> ], <expression> [ AS <alias> ], ...
[ ORDER BY <expression> [ ASC | DESC ], <expression> [ ASC | DESC ], ... ]
[ 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: grouped result projection

语法:

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 companyName = c.name
RETURN companyName, 
       count(*) AS employeeCount,
       avg(p.birthday) AS avg_birth_year
GROUP BY 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 支持丰富的数据类型,用于在图形中存储和作不同类型的信息。

基本值类型:

  • 数字INT64UINT64计算 DOUBLE 和度量值
  • 文本STRING 名称、说明和文本数据
  • 逻辑:具有三个值: BOOL TRUE、FALSE 和 UNKNOWN(对于 null 处理)
  • 时间ZONED DATETIME 使用时区信息的时间戳
  • 集合LIST<T> 对于同类型的 T多个值, PATH 图遍历结果
  • 图形元素NODEEDGE 引用图形数据

重要

某些价值类型不作为房产价值类型被支持。 特别地,所有涉及图元素参考值的值不能用作属性值(如节点列表或路径列表)。

示例文本:

42                                     -- Integer literal
"Hello, graph!"                        -- String  literal
TRUE                                   -- Boolean literal
ZONED_DATETIME('2024-01-15T10:30:00Z') -- DateTime with timezone literakl
[1, 2, 3]                              -- Literal list of integers

关键 null 处理模式:

-- Equality predicates with NULL always returns UNKNOWN
5 = NULL                              -- Evaluates to UNKNOWN (not FALSE!)
NULL = NULL                           -- Evaluates to UNKNOWN (not TRUE!)

-- Use IS NULL predicates for explicit null testing
p.nickname IS NULL                    -- Evaluates to TRUE if nickname is null
p.nickname IS NOT NULL                -- Evaluates to TRUE if nickname has a value

-- Use the COALESCE function for null-safe value selection
coalesce(p.nickname, p.firstName, '???')  -- Evaluates to first non-null value

三值逻辑含义:

-- In FILTER statements, only TRUE values pass through
FILTER p.birthday > 0        -- Removes rows where birthday is null or missing or zero

-- It's important to understand that NOT UNKNOWN = UNKNOWN
FILTER NOT (p.birthday > 0)  -- Removes rows where birthday is null or missing or positive

-- Use explicit null handling for inclusive filtering
FILTER p.birthday < 19980101 OR p.birthday IS NULL -- Includes null birthdays

注意

三值逻辑表示 NULL = NULL 返回 UNKNOWN,而不是 TRUE。 此行为会影响筛选和联接。 始终用于 IS NULL null 测试。

表达式:转换和分析数据

使用表达式可以计算、比较和转换查询中的数据。 它们类似于 SQL 中的表达式,但具有处理图形数据的额外功能。

常见表达式类型:

p.birthday < 19980101   -- Birth year comparison  
p.firstName || ' ' || p.lastName               -- String concatenation
count(*)                                       -- Aggregation
p.firstName IN ['Alice', 'Bob']                -- List membership
coalesce(p.firstName, p.lastName)              -- Null handling

复杂谓词组合:

-- Combine conditions with proper precedence
FILTER (p.birthday > 19560101 AND p.birthday < 20061231) 
  AND ((p.gender IN ['male', 'female']) OR (p.browserUsed IS NOT NULL))

-- Use parentheses for clarity and correctness
FILTER p.gender = 'female' AND (p.firstName STARTS WITH 'A' OR p.id > 1000)

字符串模式匹配:

-- Pattern matching with different operators
p.locationIP CONTAINS '192.168'      -- Substring search
p.firstName STARTS WITH 'John'       -- Prefix matching  
p.lastName ENDS WITH 'son'           -- Suffix matching

-- Case-insensitive operations
upper(p.firstName) = 'ALICE'         -- Convert to uppercase for comparison

按类别划分的内置函数:

GQL 为不同的数据处理需求提供以下函数类别:

  • 聚合函数count()、、sum()avg()min()max()汇总数据
  • 字符串函数char_length()upper()lower()用于 trim() 文本处理
  • 图形函数nodes()edges()labels()用于分析图形结构
  • 常规函数coalesce() 用于正常处理 null 值

复杂表达式的运算符优先级:

  1. 属性访问 (.
  2. 乘法/除法 (*/
  3. 加法/减法 (+-
  4. 比较 (=、 、 <><><=、 、 >=
  5. 逻辑否定(NOT
  6. 逻辑连词 (AND
  7. 逻辑析构 (OR

在上述列表中,数字较小的算符“绑定”得比数字较大的算符更紧密。 示例: NOT n.prop OR m.prop(NOT n.prop) OR m.prop 但不是“NOT (n.prop 或 m.prop)

小窍门

使用括号显式设置优先级。 复杂表达式在分组清晰时更易于读取和调试。

高级查询技术

本部分介绍用于生成复杂高效图形查询的复杂模式和技术。 这些模式超出了基本语句用法,可帮助你编写功能强大的分析查询。

复杂多语句组合

重要

Microsoft Fabric 中的图形尚不支持任意语句组合。 请参阅 有关当前限制的文章。

了解如何有效地组合复杂查询对于高级图形查询至关重要。

多步骤模式进度:

-- Build complex analysis step by step
MATCH (company:Company)<-[:workAt]-(employee:Person)
LET companyName = company.name
MATCH (employee)-[:isLocatedIn]->(city:City)
FILTER employee.birthday < 19850101
LET cityName = city.name
RETURN companyName, cityName, avg(employee.birthday) AS avgBirthday, count(employee) AS employeeCount
GROUP BY companyName, cityName
ORDER BY avgBirthday DESC

这个查询会逐步增加复杂性:查找公司、其员工、员工所在地、筛选1985年以前出生员工的公司、计算平均生日,以及总结和排序结果。

使用水平聚合:

-- Find people and their minimum distance to people working at Microsoft
MATCH TRAIL (p:Person)-[e:knows]->{,5}(:Person)-[:workAt]->(:Company { name: 'Microsoft'})
LET p_name = p.lastName || ', ' || p.firstName
RETURN p_name, min(count(e)) AS minDistance 
GROUP BY p_name
ORDER BY minDistance DESC

注释

该查询尚未被支持(已知问题)。

可变范围和高级流控制

变量跨查询语句连接数据,并启用复杂的图形遍历。 了解高级范围规则有助于编写复杂的多语句查询。

变量绑定和范围模式:

-- 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 fullNume
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 new variable for managed employee
RETURN p.firstName AS manager, e.firstName AS friend, gender

注意

同一语句中的变量不能相互引用(图形模式除外)。 使用单独的语句创建依赖变量。

高级聚合技术

GQL 支持两种不同的聚合类型,用于跨组和集合分析数据:通过可变长度模式进行 GROUP BY 垂直聚合和水平聚合。

使用 GROUP BY 进行垂直聚合

垂直聚合( RETURN 包含) GROUP BY按共享值对行进行分组,并计算每个组中的聚合:

MATCH (p:Person)-[:workAt]->(c:Company)
RETURN c.name AS companyName, 
       count(*) AS employee_count, 
       avg(p.birthday) AS avg_birth_year
GROUP BY companyName

此方法为每个公司创建一个结果行,聚合每个组中的所有员工。

使用组列表变量进行水平聚合

水平聚合计算由可变长度模式绑定的集合的聚合。 使用可变长度边缘时,边缘变量将成为一个 组列表变量 ,其中包含每个匹配路径中的所有边缘:

-- Group list variable 'edges' enables horizontal aggregation
MATCH (p:Person)-[edges:knows]->{2,4}(friend:Person)
RETURN p.firstName || ' ' || p.lastName AS person_name, 
       friend.firstName || ' ' || friend.lastName AS friend_name,
       size(edges) AS degrees_of_separation,
       avg(edges.creationDate) AS avg_connection_age,
       min(edges.creationDate) AS oldest_connection

注释

该查询尚未被支持(已知问题)。

主要区别:

  • 垂直聚合 汇总各行 - 或 - 对行进行分组,并汇总每个组中的行
  • 水平聚合 汇总单个边缘集合中的元素
  • 组列表变量仅来自可变长度边缘模式

可变长度边缘绑定上下文

了解可变长度模式中的边缘变量绑定方式至关重要:

在模式匹配期间(单一实例上下文):

-- Edge variable 'e' refers to each individual edge during filtering
MATCH (p:Person)-[e:knows WHERE e.creationDate > zoned_datetime('2000-01-01T00:00:00Z')]->{2,4}(friend:Person)
-- 'e' is evaluated for each edge in the path during matching
RETURN *

在结果表达式中(组上下文):

-- Edge variable 'edges' becomes a list of all qualifying edges
MATCH (p:Person)-[e:knows]->{2,4}(friend:Person)
RETURN size(e) AS num_edges,                    -- Number of edges in path
       e[0].creationDate AS first_edge,         -- First edge in path
       avg(e.creationDate) AS avg_age           -- Horizontal aggregation

注释

该查询尚未被支持(已知问题)。

组合垂直聚合和水平聚合

可以在复杂的分析模式中合并这两种聚合类型:

-- Find average connection age by city pairs
MATCH (p1:Person)-[:isLocatedIn]->(c1:City)
MATCH (p2:Person)-[:isLocatedIn]->(c2:City)
MATCH (p1)-[e:knows]->{1,3}(p2)
RETURN c1.name AS city1,
       c2.name AS city2,
       count(*) AS connection_paths,                  -- Vertical: count paths per city pair
       avg(size(e)) AS avg_degrees,                   -- Horizontal then vertical: path lengths
       avg(avg(e.creationDate)) AS avg_connection_age -- Horizontal then vertical: connection ages
GROUP BY city1, city2

注释

该查询尚未被支持(已知问题)。

小窍门

水平聚合始终优先于垂直聚合。 若要将组列表转换为常规列表,请使用 collect_list(edges)

注释

有关详细的聚合函数参考,请参阅 GQL 表达式和函数

错误处理策略

了解常见的错误模式有助于编写可靠的查询。

正常处理缺失的数据:

MATCH (p:Person)
-- Use COALESCE for missing properties
LET displayName = coalesce(p.firstName, p.lastName, 'Unknown')
LET contact = coalesce(p.locationIP, p.browserUsed, 'No info')
RETURN *

使用显式 null 检查:

MATCH (p:Person)
-- Be explicit about null handling
FILTER p.id IS NOT NULL AND p.id > 0
-- Instead of just: FILTER p.id > 0
RETURN *

其他信息

GQLSTATUS 代码

有关查询结果的部分中所述,GQL 报告与执行成功或潜在失败相关的丰富状态信息。 有关完整列表,请参阅 GQL 状态代码参考

保留字

GQL 保留某些关键字,不能用作变量、属性名称或标签名称等标识符。 请参阅完整列表的 GQL 保留字引用

如果需要使用保留字作为标识符,请使用反引号对其进行转义: `match``return`

若要避免转义保留字,请使用以下命名约定:

  • 对于单字标识符,请追加下划线: :Product_
  • 对于多字标识符,请使用 camelCase 或 PascalCase: :MyEntity、 、 :hasAttributetextColor

后续步骤

了解 GQL 基础知识后,建议学习路径如下:

继续构建 GQL 技能

对于初学者:

对于经验丰富的用户:

参考资料

为快速查找保留这些参考:

探索 Microsoft Fabric

了解平台:

参与

  • 共享反馈 - 帮助改进我们的文档和工具
  • 加入社区 - 与其他图形数据库从业者连接
  • 保持更新 - 遵循 Microsoft Fabric 公告了解新功能

小窍门

如果希望先学习查询语言,请先学习 快速入门教程 ,或者深入了解 图形模式

有关关键主题的更多详细信息:

快速参考:

Microsoft Fabric 中的图形: