本文提供图形查询语言示例,重点介绍核心查询模式,并展示使用真实图形架构和查询的 GQL 常见实际用例。
以下示例显示了从简单模式到复杂模式支持的 GQL 语法。
注释
在尝试这些示例之前,请设置环境以使用 GQL。 有关详细信息,请参阅 “入门 ”。 确保将客户端请求属性设置为使用 GQL,并将图形引用函数设置为图形数据源。
GQL 支持处于 预览状态。 功能和语法可能会根据反馈和正在进行的开发而变化。
核心 GQL 查询模式
WHERE:使用类似于 KQL
where
子句的标准比较和逻辑运算符。WHERE
子句基于节点和边缘属性筛选模式。 它们的工作方式类似于 KQL 或 SQL WHERE 子句,但对图形模式进行作。RETURN:使用
RETURN
语句投影匹配模式的结果。 它们指定要从图形查询输出的数据。
有关受支持的 GQL 函数和运算符的完整列表,请参阅 图形查询语言 (GQL) 参考。
基本模式匹配示例
没有变量的基本模式匹配
最简单的模式匹配任何关系,而无需引用匹配的值。
MATCH ()-[]-()
RETURN COUNT(*)
此查询查找关系图中的所有关系。 空括号 ()
表示匿名节点,并 []
表示匿名边缘。 由于我们不分配变量,因此只能对匹配项进行计数,但无法访问其属性。
与变量的模式匹配
若要访问匹配的节点和边缘,请将其分配给变量。
MATCH (n)-[e]->(n2)
RETURN COUNT(*)
n
表示源节点, e
表示 定向 边缘,并 n2
表示目标节点。 引用这些变量来访问属性,但在此示例中,你仍仅对匹配项进行计数。
访问节点属性
获得变量后,可以访问匹配节点的属性。
MATCH (person)-[e]->(target)
RETURN person.name, target.name, e.lbl
ORDER BY person.name
LIMIT 2
输出
此查询返回连接实体的名称及其之间的关系类型,按 person.name 排序,并限制为两个结果来管理输出大小。
虽然这些实体已命名 person
,但 target
没有任何限制可以确保它们实际上是一个人。
person.name | target.name | e.lbl |
---|---|---|
爱丽丝 | TechCorp | works_at |
爱丽丝 | Seattle | located_at |
按节点标签进行筛选
使用标签匹配特定类型的节点。 在变量名称后面指定带冒号的标签。
MATCH (person:Person)
RETURN person.name
ORDER BY person.name
LIMIT 5
输出
此查询仅匹配具有“Person”标签的节点并返回其名称,限制为五个结果以避免大型结果集。
person.name |
---|
爱丽丝 |
鲍勃 |
颂歌 |
大卫 |
艾玛 |
按边缘标签进行筛选
MATCH (person:Person)-[works:works_at]->(company:Company)
RETURN person.name, company.name
按不带变量的边缘标签进行筛选
对于此示例,请切换回具有“知道”关系的原始G_Doc_Transient() 图:
#crp query_graph_reference=G_Doc_Transient()
无需在不需要访问其属性时按边缘标签进行筛选,而无需将边缘分配给变量。
MATCH (p1:Person)-[:knows]->(p2:Person)
RETURN p1.name, p2.name
ORDER BY p1.name
输出
此查询通过“知道”关系查找连接到其他 Person 节点的人员节点。 边缘按标签进行筛选,但未分配给变量,因为你只需要连接的节点。
p1.name | p2.name |
---|---|
爱丽丝 | 鲍勃 |
鲍勃 | 颂歌 |
颂歌 | 大卫 |
大卫 | 艾玛 |
使用 WHERE 按属性进行筛选
使用 WHERE 子句根据属性值进行筛选。
MATCH (person:Person)
WHERE person.properties.age > 25
RETURN person.name, person.properties.age
此查询查找 25 岁以上的人,并返回其姓名和年龄。 WHERE 子句按 age 属性筛选匹配的节点。
内联属性筛选器
使用内联条件直接按模式中的属性进行筛选。
MATCH (person:Person {name: 'Bob'})
RETURN person.properties.age
此查询查找名为“Bob”的人员并返回其年龄。 语法 {name: 'Bob'}
筛选名称属性等于“Bob”的节点。
多个内联条件
内联指定多个属性条件。
MATCH (person:Person {name: 'Bob'})
WHERE person.properties.age = 30
RETURN person as Bob
此查询查找具有指定名称和年龄的人员。 它将人员节点返回为“Bob”。
可变长度路径
对多跃点关系使用具有限定符的可变长度路径模式:
MATCH (s)-[]->{1,3}(e)
RETURN s.name, e.name
此查询查找包含 1 到 3 个跃点的路径。
{1,3}
限定符设置最小和最大路径长度。
未绑定的可变长度路径
指定可变长度路径的开放范围:
MATCH (center)-[]->{1,}(connected)
WHERE center.name = 'Alice'
RETURN DISTINCT connected.name
此查询查找可通过一个或多个跃点的路径从 Alice 访问的所有节点。
{1,}
限定符表示“一个或多个跃点”。
路径函数
使用路径函数提取有关匹配路径的信息,包括构成路径的节点和关系:
MATCH fof = (person)-[:knows]->{2,2}()
RETURN fof, NODES(fof) AS NodesOfPath, RELATIONSHIPS(fof) AS EdgesOfPath
LIMIT 1
此查询使用“知道”关系查找长度正好为 2 个跃点的路径。 路径变量 fof
包含整个路径作为交替节点和边缘的数组。 该 NODES()
函数仅从路径中提取节点,并 RELATIONSHIPS()
仅提取边缘。
输出
fof | NodesOfPath | EdgesOfPath |
---|---|---|
[{"id": "p3", "lbl": "Person", "name": "Carol", "properties": {"age": 28}, "$labels": ["Person"]}, {"source": "p3", "target": "p4", "lbl": "knows", "since": 2022, "$labels": ["knows"]}, {"id": "p4", "lbl": "Person", "name": "David", "properties": {"age": 35}, "$labels": ["Person"]}, {"source": "p4", "target": "p5", "lbl": "knows", "since": 2023, "$labels": ["knows"]}, {"id": "p5", "lbl": "Person", "name": "Emma", "properties": {"age": 26}, "$labels": ["Person"]}] |
[{"id": "p3", "lbl": "Person", "name": "Carol", "properties": {"age": 28}, "$labels": ["Person"]}, {"id": "p4", "lbl": "Person", "name": "David", "properties": {"age": 35}, "$labels": ["Person"]}, {"id": "p5", "lbl": "Person", "name": "Emma", "properties": {"age": 26}, "$labels": ["Person"]}] |
[{"source": "p3", "target": "p4", "lbl": "knows", "since": 2022, "$labels": ["knows"]}, {"source": "p4", "target": "p5", "lbl": "knows", "since": 2023, "$labels": ["knows"]}] |
基本属性筛选
基于单个属性条件筛选节点:
MATCH (person:Person)
WHERE person.properties.age > 26
RETURN person.name, person.properties.age
ORDER BY person.name
输出
此查询查找属性大于 26 的所有 Person
节点 age
。
person.name | person.properties.age |
---|---|
鲍勃 | 30 |
颂歌 | 28 |
大卫 | 35 |
使用 AND 筛选范围
若要创建范围,请组合多个条件:
MATCH (person:Person)
WHERE person.properties.age >= 28 AND person.properties.age <= 35
RETURN person.name, person.properties.age
此查询显示年龄在 28 到 35 岁(含)之间的人员。
Edge 属性筛选
按边缘属性进行筛选以查找特定类型的关系。
MATCH (person:Person)-[wa:works_at]->(c:Company)
WHERE wa.since >= 2022
RETURN person.name, c.name, wa.since
此查询显示 2022 年或更高版本开始在公司工作的人员。 它按 since
关系的属性 works_at
进行筛选。
字符串模式匹配
使用字符串函数匹配文本模式。
MATCH (person:Person)
WHERE person.name STARTS WITH 'Al'
RETURN COUNT(*)
此查询统计名称以“Al”开头的人。 它提供快速摘要,无需返回大型结果集。
字符串包含匹配
检查字符串是否具有特定的子字符串。
MATCH (person:Person)
WHERE person.name CONTAINS 'i'
RETURN person.name
此查询查找名称在字符串中的任何位置都有“i”的人员。 此匹配区分大小写。
不等比较
使用比较运算符排除特定值:
MATCH (person:Person)-[wa:works_at]->(company:Company)
WHERE person.properties.age > 25 AND company.name <> 'TechCorp'
RETURN person.name, company.name
此查询显示超过 25 名在“TechCorp”以外的公司工作的人员。
Null 值检查
检查是否存在属性值。
MATCH (person:Person)
WHERE person.properties.age IS NOT NULL
RETURN person.name, person.properties.age
此查询查找记录了年龄的所有人员(非 null 年龄属性)。
逻辑 OR作
使用 OR 匹配多个条件
MATCH (person:Person)
WHERE person.properties.age > 30 OR person.name CONTAINS 'a'
RETURN person.name, person.properties.age
此查询查找年龄超过 30 岁或姓名为“a”的人员。
返回特定属性
从匹配的节点返回单个属性。
MATCH (person:Person)
RETURN person.name, person.properties.age
此查询返回每个 Person 节点的名称和年龄属性。 结果中的每个行都显示这两个值。
使用别名返回
为了清楚起见,请使用别名重命名输出列。
MATCH (person:Person)-[employment:works_at]->(company:Company)
RETURN person.name AS Employee, company.name AS Company, employment.since AS WorkingSince
此查询返回具有描述性列标题的员工姓名、公司名称和就业开始日期。
返回属性包 (JSON 对象)
通过在 RETURN 子句中组合多个属性创建自定义 JSON 对象。
MATCH (person:Person)
RETURN {age: person.properties.age, name: person.name} AS myPropertyBag
LIMIT 1
输出
此查询将创建自定义 JSON 对象(属性包),其中包含匹配的 Person 节点中的选定属性。 属性包将人员的年龄和姓名合并为单个结构化对象。
myPropertyBag |
---|
{ “age”: 28, “name”: “Carol” } |
返回整个节点和边缘
MATCH (person:Person)-[e]->(company:Company)
WHERE person.name = 'Alice'
RETURN person, e, company
输出
此查询返回 Alice 与公司(包括所有属性)关系的完整节点和边缘对象。
人 | e | 公司 |
---|---|---|
{“id”:“p1”,“lbl”:“Person”,“name”:“Alice”,“properties”:{“age”: 25}} | {“source”:“p1”,“target”:“c1”,“lbl”:“works_at”,“since”:2020} | {“id”:“c1”,“lbl”:“Company”,“name”:“TechCorp”,“properties”:{}} |
计数匹配模式
使用 COUNT\ 对模式匹配项数进行计数。
MATCH (person:Person)-[:likes]->(p2:Person)
RETURN person.name, COUNT(*) AS LikesGiven
此查询按人员姓名统计每个人喜欢和对结果进行分组的人数。
使用 MIN 和 MAX 进行聚合
查找所有匹配项的最小值和最大值。
MATCH (person:Person)
RETURN MIN(cast(person.properties.age as int)) AS Youngest, MAX(cast(person.properties.age as int)) AS Oldest
此查询查找图形中所有人员中最年轻和年龄最大的年龄。
将值收集到数组中
使用COLLECT_LIST将多个值收集到数组中。
MATCH (person:Person)
RETURN COLLECT_LIST(person.name) AS AllNames
此查询将所有人员姓名收集到单个数组中。
返回非重复值
从结果中删除重复项。
MATCH (person:Person)-[]->(company:Company)
RETURN DISTINCT company.name
此查询仅返回一次唯一的公司名称,即使多个人连接到同一家公司也是如此。
返回有序结果
使用 ORDER BY 对结果进行排序。
MATCH (person:Person)
RETURN person.name, person.properties.age
ORDER BY cast(person.properties.age as int) DESC
此查询以降序返回按年龄排序的人,先按年龄排序。
限制结果计数
限制返回的结果数。
MATCH (person:Person)
WHERE person.properties.age > 25
RETURN person.name
ORDER BY cast(person.properties.age as int)
LIMIT 5
此查询仅返回 25 岁以上的前 5 个人,按年龄排序。
可比 KQL: 类似于 KQL project
、 summarize
、 sort
和 take
运算符。
高级模式示例
使用高级模式可以匹配复杂的图形结构和标签组合。
标签联合 (OR)
匹配具有任何指定标签的节点:
MATCH (entity:Person | Company)
RETURN entity
此查询匹配具有“人员”或“公司”标签的节点。 管道符号 |
表示标签的逻辑 OR。
标签交集 (AND)
匹配具有所有指定标签的节点:
MATCH (person:Person & Male)
RETURN person.name
此查询匹配同时具有“Person”和“Male”标签的节点。 与数 &
表示标签的逻辑 AND。
标签否定 (NOT)
匹配没有指定标签的节点:
MATCH (person:!Female)
RETURN person.name
此查询与没有“女性”标签的所有节点匹配。 感叹号 !
表示标签的逻辑 NOT。
具有精确范围的可变长度路径
匹配具有特定跃点数的路径:
MATCH (s)-[es]->{2,2}(e)
RETURN s, es, e
此查询查找长度正好为两个跃点的路径。
{2,2}
限定符将最小路径长度和最大路径长度设置为 2。
具有开放范围的可变长度路径
匹配具有最小跃点数但没有最大值的路径:
MATCH (s)-[p]->{1,}(e)
RETURN s, e, p
此查询查找长度为一个或多个跃点的路径。
{1,}
限定符表示一个或多个没有上限的跃点。
零长度路径
将节点与自身匹配(标识关系):
MATCH (n)-[]->{0,0}(same_n)
RETURN n
此查询通过零长度路径匹配每个节点本身。
{0,0}
限定符将路径长度设置为零,因此每个节点与自身配对。
命名路径变量
将整个路径分配给变量供以后使用:
MATCH p = (person:Person)-[:works_at]->(company:Company)
RETURN p
此查询将整个模式分配给变量 p
,可以在查询的其他部分返回或使用该模式。 路径变量具有节点和边缘的完整序列。
可选匹配
用于 OPTIONAL MATCH
查找可能不存在的模式,当模式不匹配时返回空值:
MATCH (p:Person)
WHERE p.properties.age < 30
OPTIONAL MATCH (p)->(c:City)
WHERE c.name <> 'Seattle'
RETURN p.name as Person, c.name as City
此查询查找年龄小于 30 的所有 Person
节点,并可以选择匹配它们连接到的城市(不包括西雅图)。 如果某个人未连接到任何城市(或仅连接到西雅图),则 City 列将返回空,但结果中仍包含该人员。
输出
可选匹配可确保仍返回没有城市连接的人员:
人员 | City |
---|---|
颂歌 | 波特兰 |
艾玛 | 波特兰 |
爱丽丝 |
多跃点命名路径
创建跨多个关系的命名路径:
MATCH full_path = (s)-[first_edge]->(middle)-[second_edge]->(e)
RETURN full_path, s.name, e.name
此查询创建一个命名路径变量,该变量 full_path
捕获双跃点模式,并从 s 和 e 节点返回特定属性。
可比 KQL: 使用高级 graph-match
运算符功能进行复杂的模式匹配。
复杂的多模式示例
使用 FILTER 交叉产品筛选
使用多个单独的 MATCH
模式时,GQL 会创建所有匹配组合的交叉积。 通过 FILTER
关键字,可以根据涉及来自不同模式的变量的条件筛选此跨产品。
此示例演示如何筛选人员和城市的交叉乘积:
MATCH (p:Person)
MATCH (c:City)
FILTER p.name = 'Carol' or c.name = 'Seattle'
RETURN p.name as Person, c.name as City
LIMIT 2
输出
人员 | City |
---|---|
颂歌 | 波特兰 |
大卫 | Seattle |
此查询演示关键字 FILTER
如何在所有 Person 节点和所有 City 节点的交叉乘积上运行,仅返回人员名称为“Carol”或城市名称为“Seattle”的组合。
具有公司筛选器 的 跨城镇赞
此示例在一个语句中合并了多个模式和筛选器:
- 找到一对 p1 喜欢 p2 的人。
- 将每个人链接到他们的家乡。 p1 的城市名称必须 以“San”开头,p2 必须位于 不同的城市。
- 请确保 p2 在 TechCorp 中正常工作。
- 仅包括两人 年龄不同的对。
第一个 RETURN
显示每个资格赛(人员、他们的城市和公司),以便可以查看原始结果。
第二 RETURN
个聚合所有匹配项以输出单个值:满足这些条件 的所有“喜欢”人员 (p2)的平均年龄。
MATCH (p1:Person)-[:likes]->(p2:Person),
(p1)-[:located_at]->(home:City),
(p2)-[:located_at]->(home2:City),
(p2)-[:works_at]->(work:Company {name: 'TechCorp'})
WHERE cast(p1.properties.age as int) <> cast(p2.properties.age as int) and home.name <> home2.name and home.name starts with 'San'
RETURN p1.name, p2.name, home.name, work.name, home2.name
输出
p1.name | p2.name | home.name | work.name | home2.name |
---|---|---|---|---|
大卫 | 爱丽丝 | 旧金山 | TechCorp | Seattle |
MATCH (p1:Person)-[:likes]->(p2:Person),
(p1)-[:located_at]->(home:City),
(p2)-[:located_at]->(home2:City),
(p2)-[:works_at]->(work:Company {name: 'TechCorp'})
WHERE cast(p1.properties.age as int) <> cast(p2.properties.age as int) and home.name <> home2.name and home.name starts with 'San'
RETURN AVG(cast(p2.properties.age as int)) AS AvgAgeLikedAcrossTowns
输出
AvgAgeLikedAcrossTowns |
---|
二十五 |
此示例演示了 GQL 如何通过跨变量筛选、内联属性匹配、字符串模式匹配和聚合来表达复杂的多模式查询,所有这些查询都在一个可读语句中。
使用 DURATION 函数进行时态数据分析
GQL 提供对使用持续时间函数进行临时数据分析的全面支持。 通过这些函数,可以使用时间戳对图形数据执行基于时间的筛选、计算和比较。
支持的持续时间单位
该 DURATION()
函数支持使用灵活、不区分大小写的语法并返回一个 timespan
对象的各种时间单位:
时间单位 | 支持的名称 | Example | Timespan 输出 |
---|---|---|---|
日 |
days 、day |
DURATION({days: 7}) |
7.00:00:00 |
Hours |
hours 、hour 、HOURS |
DURATION({hours: 24}) |
1.00:00:00 |
纪要 |
minutes 、minute 、MINUTES |
DURATION({minutes: 30}) |
00:30:00 |
秒 |
seconds 、second 、SECONDS 、secOnd |
DURATION({seconds: 45}) |
00:00:45 |
毫秒 |
milliseconds 、millisecond |
DURATION({milliseconds: 500}) |
00:00:00.5000000 |
微秒 |
microseconds 、microsecond 、micRosecond |
DURATION({microseconds: 1000}) |
00:00:00.0010000 |
纳 秒 |
nanoseconds 、nanosecond 、nanoSecond |
DURATION({nanoseconds: 1000000}) |
00:00:00.0010000 |
可以在单个持续时间对象中组合多个单位: DURATION({days: 1.8, minutes: 8, seconds: 7})
返回 1.00:08:07
。
复杂的时态边界分析
将持续时间函数与时间戳算术相结合,以便进行精确的时态筛选:
MATCH (system:System)-[event:generated]->(alert:Alert)
WHERE event.event_timestamp <= zoned_datetime("2012-01-01 08:00:00.0") + DURATION({days: 3})
AND event.event_timestamp > zoned_datetime("2012-01-01 08:00:00.0") + DURATION({minutes: 1})
RETURN
system.name,
alert.severity,
event.event_timestamp,
DURATION_BETWEEN(zoned_datetime("2012-01-01 08:00:00.0"), event.event_timestamp) AS time_since_baseline
ORDER BY event.event_timestamp
此查询查找在特定时间范围内生成的警报(基线日期后的 1 分钟到 3 天),并计算基线与每个事件之间的持续时间。
输出
system.name | alert.severity | event_timestamp | time_since_baseline |
---|---|---|---|
WebServer01 | 警告 | 2012-01-01T08:01:30.0Z | 00:01:30 |
Database02 | 危急 | 2012-01-02T20:15:45.0Z | 1.12:15:45 |
负载均衡器 | 信息 | 2012-01-04T16:30:00.0Z | 3.08:30:00 |
社交网络用例:好友建议
社交媒体平台使用 GQL 根据相互关系建议潜在的朋友。
我们将使用 LDBC 社交网络基准数据集(请参阅 GQL 示例数据)。
设置图形引用以指向 LDBC 数据集。
#crp query_graph_reference=graph('LDBC_SNB_Interactive')
通过相互联系查找潜在的朋友。
MATCH (p1:PERSON {firstName: 'Karl', lastName: 'Muller'})-[:KNOWS]-(p2:PERSON)-[:KNOWS]-(p3:PERSON), (p1)-[:IS_LOCATED_IN]-(c1:PLACE), (p3)-[:IS_LOCATED_IN]-(c1) WHERE p1.id <> p3.id RETURN DISTINCT p3.firstName, p3.lastName
输出
此查询建议有相互联系并位于同一位置的卡尔的朋友。
p3.firstName | p3.lastName |
---|---|
阿尔佛雷德 | 霍夫曼 |
汉斯 | 贝克尔 |
威廉 | 穆勒 |