在图数据库开发中,我们常常需要精准描述节点与边的复杂关联关系。nGQL 的图模式作为核心语法,就像一把 “万能钥匙”,能帮助我们高效匹配各种图结构。本文将基于 NebulaGraph 官方定义,系统拆解 9 大核心图模式(含 2 种扩展模式),结合可验证的实操示例,带大家掌握图查询的底层逻辑。
图模式是 nGQL 描述图结构的核心语法,通过节点、边及其属性的组合,实现从简单点查询到多层路径匹配的复杂操作。无论是社交网络中的关注关系,还是供应链中的多级溯源,本质都是这些模式的灵活组合。掌握图模式,就能像 “拼乐高” 一样构建任意复杂的查询逻辑。
语法:(节点变量[:Tag]{属性})
ngql
// 查询名为“Yao Ming”的球员(带Tag和属性)
MATCH (v:player{name: "Yao Ming"})
RETURN v._vid AS 顶点ID, v.name AS 姓名, v.age AS 年龄;
// 统计所有球队节点(匿名节点,仅计数)
MATCH () :team
RETURN count(*) AS 球队总数;
v
)仅在需要获取属性时定义,否则可匿名(如()
)。语法:(起点)-[边模式]->(终点)
(出边)、(起点)<-[边模式]-(终点)
(入边)
->
(出边)、<-
(入边),无向边-
仅测试用[:follow]
(单一类型)、[:follow|:serve]
(多类型匹配)[e:follow{degree: 95}]
(带属性的边变量)ngql
// 查询LeBron James关注的对象(出边,带边属性)
MATCH (v1:player{name: "LeBron James"})-[e:follow]->(v2)
RETURN v2.player.name AS 被关注者, e.degree AS 关注度;
// 查询关注LeBron James的人(入边)
MATCH (v1:player{name: "LeBron James"})<-[e:follow]-(v2)
RETURN v2.player.name AS 关注者;
语法:(节点:Tag)
(需提前创建 Tag)
ngql
// 创建球员Tag(强Schema定义)
CREATE TAG IF NOT EXISTS player(
name string,
age int,
position string
);
// 匹配所有球员节点(带Tag过滤)
MATCH (p:player)
RETURN p.name, p.position
LIMIT 5;
CREATE TAG
声明。语法:(节点{属性键: 值})
或 [边{属性键: 值}]
{name: "Tim Duncan", age: 42}
(精确匹配)age > 30
、name STARTS WITH "Y"
position IN ["center", "forward"]
ngql
// 查询年龄35-40岁的球员(属性表达式)
MATCH (p:player{age: [35..40]})
RETURN p.name, p.age;
// 匹配关注度>90的边
MATCH (a)-[e:follow{degree: > 90}]->(b)
RETURN a.name AS 粉丝, b.name AS 偶像;
语法:[边变量:边类型{属性}]
[:serve]
(效力关系)、[:follow|:coach]
(多类型兼容)e
获取边属性(如type(e)
获取边类型,properties(e)
获取所有属性)ngql
// 查询球员与球队的效力关系及加盟年份
MATCH (p:player)-[e:serve{start_year: 2003}]->(t:team)
RETURN p.name AS 球员, t.name AS 球队, e.start_year AS 加盟时间;
语法:[*n..m]
(n = 最小边数,m = 最大边数,可省略一端)
[*2]
(2 步,3 个节点)[*2..5]
(2-5 步)、[*..5]
(1-5 步,默认最小 1)[*]
(1 到无穷步,等价于[*1..]
)ngql
// 查询2步内的球队关联(球员→球队→城市)
MATCH (p:player)-[*2]->(c:city)
RETURN p.name AS 球员, c.name AS 城市, length(p) AS 路径长度;
// 错误示例:当前版本不支持单端无限(如`[*3..]`,需显式最大长度)
// 正确写法:MATCH (a)-[*3..10]->(b) ...
语法:路径变量 = (起点)-[*n..m]->(终点)
nodes(路径变量)
:获取路径中所有节点(数组)edges(路径变量)
:获取路径中所有边(数组)length(路径变量)
:获取边数(路径长度)ngql
// 查询3步内的完整路径详情
MATCH p = (v:player)-[*3]->(t:team)
RETURN
nodes(p)[0].name AS 起点球员,
nodes(p)[-1].name AS 终点球队,
edges(p)[1].degree AS 中间边属性;
语法:()
(未命名节点,仅用于路径连接)
(a)-[:follow]->()
(仅关注 “a 关注了某个节点”,不关心目标节点详情)(a)-[*2]->(b)
等价于 (a)-[]->()-[]->(b)
ngql
// 查询所有有关注行为的球员(不关心被关注者)
MATCH (p:player)-[:follow]->()
RETURN DISTINCT p.name AS 活跃用户;
根据 NebulaGraph 文档,以下模式尚未完全实现或需特殊处理:
(a)-[]-(b)
(实际按双向边处理,需用BOTH
关键字显式查询) ngql
// 实验性写法(需确认版本支持)
MATCH (a)-[*1..2]-()-(b) RETURN a, b;
OPTIONAL MATCH
ngql
// 查询自环边(如“自我关注”)
OPTIONAL MATCH (a)-[*0]->(a) RETURN a.name AS 自环节点;
需求:查询 “关注了勇士队球员的球员的关注对象”
ngql
MATCH (fan:player)-[:follow]->(player:player)-[:serve]->(team:team{name: "Warriors"})
-[:follow]->(target:player)
RETURN fan.name AS 粉丝, target.name AS 潜在关注对象;
模式组合:player→follow→player→serve→team→follow→player
,通过链式多点关联实现多层过滤。
需求:查找从供应商到制造商的 3-5 级物流路径,且运输时间 < 3 天
ngql
MATCH p = (supplier:node)-[*3..5:transport{days: < 3}]->(manufacturer:node)
YIELD
nodes(p)[0].name AS 起点,
nodes(p)[-1].name AS 终点,
length(p) AS 运输步数;
关键点:结合变长模式[*3..5]
和边属性过滤{days: < 3}
,精准匹配符合条件的路径。
需求:查询既是 “全明星球员”(all_star Tag)且得分 > 20 分的球员
ngql
// 先创建复合Tag(实际通过属性过滤实现)
MATCH (p:player)
WHERE p.avg_score > 20 AND "all_star" IN tags(p)
RETURN p.name, p.avg_score;
注意:nGQL 不支持直接匹配多 Tag,需通过tags()
函数和WHERE
子句组合实现。
ngql
// 错误:未指定边方向,默认按出边处理(实际数据可能是入边)
MATCH (a)-[:follow]-(b) RETURN b.name; // 可能返回空结果
// 正确:显式指定边方向(根据数据模型选择->或<-)
MATCH (a)-[:follow]->(b) RETURN b.name; // 或 MATCH (a)<-[:follow]-(b) ...
ngql
// 错误:[*..5]默认最小长度为1,无法匹配0步(自身节点)
MATCH (a)-[*..5]->(a) RETURN a.name; // 无结果
// 正确:显式包含0步(需版本支持,部分场景用OPTIONAL MATCH)
MATCH (a)-[*0..5]->(b) RETURN a.name, b.name;
ngql
// 错误:模仿openCypher动态使用未定义的Label
MATCH (v:unknownLabel) RETURN v; // 报错,nGQL的Tag必须提前创建
// 正确流程:先创建Tag再使用
CREATE TAG unknownLabel(property string);
MATCH (v:unknownLabel) RETURN v;
basketballplayer
数据集,通过SOURCE
命令导入后,用MATCH (v:player) LIMIT 10;
验证基础模式。ngql
EXPLAIN MATCH (a:player)-[*2]->(b) RETURN a, b;
GetNeighbors
(单步)或Traverse
(变长)操作符,确保模式被正确解析。(a)-[]->(b)
,再增加[*2]
和属性条件,逐步排除错误。(a)-[]->(b)
,再逐步添加[*n..m]
和属性过滤,配合EXPLAIN
优化执行效率。features
目录有 2500 + 经过测试的 nGQL 示例掌握图模式,就掌握了 nGQL 的核心能力。无论是简单的点查询,还是多层级的路径分析,本质都是这些基础模式的排列组合。建议初学者从单点和单边模式入手,通过官方示例反复实操,逐步过渡到变长和属性组合模式。遇到问题时,多利用EXPLAIN
和PROFILE
分析执行计划,确保查询既正确又高效。
如果你在实操中遇到具体问题,欢迎在评论区留言,我们可以一起拆解执行逻辑,优化查询语句。觉得内容实用的话,别忘了收藏关注,后续会分享更多 nGQL 性能优化和生产环境实战技巧,助你在图数据库开发中少走弯路!