图变量¶
图变量用于存储子图以进行查询和计算。关键字GRAPH用于定义图变量。
定义图变量有两种方式:
- 基于图查询:使用 MATCH 语句从现有图中检索子图,并将其存储在图变量中。
- 基于图类型:使用预定义的图类型声明一个图变量,然后使用 IMPORT 语句向其中导入数据。
前提条件¶
- 已创建图。更多信息,请参见 CREATE GRAPH。
- 具备在当前 Schema 执行
MATCH ANY GRAPH操作的权限,或具备在所查询的图上执行MATCH操作的权限。更多信息,请参见角色与权限。
使用说明¶
- 不支持通过 DML 修改其中的图数据(如对点、边进行
INSERT、DELETE,或使用SET修改点、边属性)。 - 不能在其上创建索引等结构。
- 允许执行
SET <graph_variable>.clear()用于清空图变量后重新导入数据。
语法¶
基于查询定义图变量¶
- graph_variable_definition_from_query
graph_variable_definition_from_query ::=
'PROPERTY'? 'GRAPH' graph_variable
( 'TYPED'? 'GRAPH' '{'
(
(('NODE' | 'VERTEX') 'TYPE'? node_type_name '(' node_type_filler ')')
|
(('EDGE' | 'RELATIONSHIP') 'TYPE'? edge_type_name
(
'(' source_node_type_name ')' '-[' edge_type_filler ']->' '(' destination_node_type_name ')'
|
'(' destination_node_type_name ')' '<-[' edge_type_filler ']-' '(' source_node_type_name ')'
|
'(' source_node_type_name ')' '~[' edge_type_filler ']~' '(' destination_node_type_name ')'
)
)
)
(
','
(
(('NODE' | 'VERTEX') 'TYPE'? node_type_name '(' node_type_filler ')')
|
(('EDGE' | 'RELATIONSHIP') 'TYPE'? edge_type_name
(
'(' source_node_type_name ')' '-[' edge_type_filler ']->' '(' destination_node_type_name ')'
|
'(' destination_node_type_name ')' '<-[' edge_type_filler ']-' '(' source_node_type_name ')'
|
'(' source_node_type_name ')' '~[' edge_type_filler ']~' '(' destination_node_type_name ')'
)
)
)
)*
'}' )? '=' 'GRAPH' '{' use_clause? match_statement return_statement '}'
基于图类型定义图变量¶
- graph_variable_definition_from_type
graph_variable_definition_from_type ::=
'PROPERTY'? 'GRAPH' graph_variable 'TYPED' graph_type_name
清除图变量¶
- graph_variable_clear
graph_variable_clear ::=
'SET' graph_variable '.clear()'
参数¶
graph_variable¶
要定义的图变量的名称。graph_variable可以是常规标识符或使用反引号(`)包围的分隔标识符。有关标识符的更多信息,请参见标识符命名规则。
node_type_name¶
待定义的图变量中的点类型的名称。此处指定的点类型必须在后续的 MATCH 及 RETURN 语句中指定。
node_type_filler¶
待定义的图变量中的点类型的属性与标签。
此处指定的属性与标签必须与后续 MATCH 及 RETURN 语句中指定的相应点类型的属性与标签保持一致。
关于此参数的更多信息,请参见 CREATE GRAPH TYPE 中的语法图。
edge_type_name¶
待定义的图变量中的边类型的名称。此处指定的边类型必须在后续的 MATCH 及 RETURN 语句中指定。
source_node_type_name¶
待定义的图变量中边类型的起始点类型的名称。此处指定的点类型必须在后续的 MATCH 及 RETURN 语句中指定。
destination_node_type_name¶
待定义的图变量中边类型的目标点类型的名称。此处指定的点类型必须在后续的 MATCH 及 RETURN 语句中指定。
edge_type_filler¶
待定义的图变量中边类型的属性与标签。
此处指定的属性与标签必须与后续 MATCH 及 RETURN 语句中指定的相应边类型的属性与标签保持一致。
关于此参数的更多信息,请参见 CREATE GRAPH TYPE 中的语法图。
use_clause¶
USE 子句指定在 MATCH 语句中使用的图。若要使用的图已设置为主图,则可省略该子句。更多信息,请参见 USE。
match_statement¶
MATCH 语句检索将存储在图变量中的子图,该子图必须至少包含一个点。
如果指定了node_type_name或edge_type_name,则相应的点类型或边类型必须在 MATCH 语句中指定。
更多信息,请参见 MATCH。
return_statement¶
RETURN 语句指定将存储在图变量中的子图,该子图必须至少包含一个点。
如果指定了node_type_name或edge_type_name,则相应的点类型或边类型必须在 RETURN 语句中指定。
更多信息,请参见 RETURN。
graph_type_name¶
现有图类型的名称。图变量将使用该图类型定义的结构创建,但不包含数据。之后可以使用 IMPORT 语句导入数据。
行为¶
向图变量导入数据¶
基于图类型定义图变量后,可以使用USE子句切换到该图变量,然后使用 IMPORT 语句填充数据。不允许向非空图变量导入数据。若要重新导入数据,必须先使用SET <graph_variable>.clear()清除图变量。
清除图变量¶
SET <graph_variable>.clear()语句从图变量中移除所有点和边。图变量本身及其类型定义保留。清除后,可以向图变量导入新数据。
在图变量上运行过程¶
向图变量填充数据后,可以使用USE子句切换到该图变量并在其上运行过程。
示例¶
以下示例基于示例数据集。
基于查询定义图变量¶
'''
GRAPH g = GRAPH { USE movie MATCH (a@Actor) RETURN a }
USE g
MATCH (v)
RETURN v.id, v.name AS name
ORDER BY v.id
LIMIT 3
'''
上述语句定义了一个图变量 g,用于存储所有 Actor 点,然后查询该变量以按 ID 顺序检索三个点。
返回:
+------+---------------+
| v.id | name |
+------+---------------+
| 2 | Mark Hamill |
| 3 | Harrison Ford |
| 4 | Carrie Fisher |
+------+---------------+
基于查询定义图变量(内联图类型定义)¶
Note
使用内联图类型定义的图变量必须指定初始值(即= GRAPH { query }部分不可省略)。如需定义空图变量,请使用预定义的具名图类型,请参见下文示例基于图类型定义图变量。
'''
GRAPH g TYPED GRAPH {
NODE TYPE Actor (LABEL Person {id INT64 PRIMARY KEY, name STRING, birthDate DATE } ),
NODE TYPE Movie (LABEL Movie {id INT64 PRIMARY KEY, name STRING }),
EDGE TYPE Act (Actor)-[LABEL Act{}]->(Movie)
} = GRAPH { USE movie MATCH (n@Actor)-[r@Act]->(m@Movie) RETURN n, m, r }
USE g
MATCH (v1@Actor) -[e]-> (v2@Movie)
RETURN v1.name AS name
ORDER BY name
LIMIT 3
'''
上述语句定义了一个图变量g,其中预定义了点类型Actor和Movie以及边类型Act。图变量g存储了 MATCH 语句中检索得到的Actor和Movie类型的点以及Act类型的边。
返回:
+------------------+
| name |
+------------------+
| Aaron Eckhart |
| Ada Lonati |
| Adam Alexi-Malle |
+------------------+
基于图类型定义图变量¶
以下示例定义了一个具有预定义图类型的空图变量,并从表变量导入数据。
'''
-- 创建图类型
CREATE GRAPH TYPE IF NOT EXISTS empty_typed_gt AS {
NODE Person (
LABEL Person {
id INT PRIMARY KEY,
name STRING
}
),
EDGE Knows (Person)-[:Knows{
id INT,
MULTIEDGE KEY()
}]->(Person)
}
'''
'''
GRAPH g TYPED empty_typed_gt
USE g {
TABLE persons TYPED TABLE {id INT, name STRING} =
{id: 1, name: "Alice"},
{id: 2, name: "Bob"}
TABLE edges TYPED TABLE {src_id INT, dst_id INT, id INT} =
{src_id: 1, dst_id: 2, id: 10}
IMPORT INTO GRAPH {
NODE (p@Person{ id: id, name: name }) FROM persons,
EDGE (id:src_id)-[e@Knows{ id: id }]->(id:dst_id) FROM edges
}
MATCH (p@Person)-[e@Knows]->(q@Person)
RETURN p.id, p.name, q.id, q.name, e.id
ORDER BY e.id
}
'''
返回:
+------+--------+------+--------+------+
| p.id | p.name | q.id | q.name | e.id |
+------+--------+------+--------+------+
| 1 | Alice | 2 | Bob | 10 |
+------+--------+------+--------+------+
清除图变量¶
以下示例展示如何清除图变量并在之后查询它。
'''
GRAPH g = GRAPH{ USE movie MATCH (a@Actor) RETURN a }
SET g.clear()
USE g
MATCH (v)
RETURN v.id, v.name
'''
清除后,图变量不包含数据,因此查询返回空结果:
+------+--------+
| v.id | v.name |
+------+--------+
+------+--------+
在图变量上运行过程¶
以下示例定义了一个图变量,填充数据,然后在其上运行一个使用活跃集和聚合的过程。
'''
-- 创建过程
CREATE OR REPLACE PROCEDURE proc_graph_active_set_agg() RETURNS (cnt INT) AS {
VALUE active_set ACTIVE_SET
VALUE cnt SumAgg<INT> = 0
MATCH (s@Actor) WHERE s.id < 5
FINALLY {
SET active_set = s
}
MATCH (v@Actor)
WHERE v IN active_set
PER NODE (v) {
SET @cnt += 1
}
RETURN @cnt
}
'''
'''
-- 在图变量上运行过程
GRAPH g = GRAPH{ USE movie MATCH (a@Actor) RETURN a }
USE g
CALL proc_graph_active_set_agg()
RETURN cnt
'''
返回:
+-----+
| cnt |
+-----+
| 3 |
+-----+
图变量上的迭代计算¶
以下示例展示了图变量上的迭代计算模式。每轮迭代中,一个点(由迭代索引标识)被"激活",其val属性值加 1。计算结果导出到表变量后,清空图变量并重新导入更新后的数据,进入下一轮迭代。
-
创建图类型。
''' CREATE GRAPH TYPE IF NOT EXISTS gv_iter_gt AS { NODE Person ( LABEL Person { id INT PRIMARY KEY, val INT } ), EDGE Link (Person)-[:Link{ id INT, MULTIEDGE KEY() }]->(Person) } ''' -
创建临时图并导入数据。
创建一个临时图,导入 6 个点(ID 为 0–5,初始
val均为 0)和 5 条边,构成一条链式结构(0→1→2→3→4→5)。''' CREATE TEMPORARY GRAPH IF NOT EXISTS #gv_iter_base TYPED gv_iter_gt ''' ''' USE #gv_iter_base { TABLE nodes TYPED TABLE {id INT, val INT} = {id: 0, val: 0}, {id: 1, val: 0}, {id: 2, val: 0}, {id: 3, val: 0}, {id: 4, val: 0}, {id: 5, val: 0} TABLE edges TYPED TABLE {src INT, dst INT, eid INT} = {src: 0, dst: 1, eid: 1}, {src: 1, dst: 2, eid: 2}, {src: 2, dst: 3, eid: 3}, {src: 3, dst: 4, eid: 4}, {src: 4, dst: 5, eid: 5} IMPORT INTO GRAPH { NODE (p@Person{ id: id, val: val }) FROM nodes, EDGE (id: src)-[e@Link{ id: eid }]->(id: dst) FROM edges } } '''导入后的图结构如下:
(0)--1-->(1)--2-->(2)--3-->(3)--4-->(4)--5-->(5)所有点的
val初始值均为 0。 -
创建过程。
本示例需要三个过程:一个用于将数据导入图变量,一个用于执行单步计算,一个用于驱动外层迭代循环。
导入过程:将表变量中的点和边数据导入图变量。
''' CREATE OR REPLACE PROCEDURE gv_iter_import(nodes TABLE, edges TABLE) AS { IMPORT INTO GRAPH { NODE (p@Person{ id: id, val: val }) FROM nodes, EDGE (id: src)-[e@Link{ id: eid }]->(id: dst) FROM edges } } '''单步计算过程:执行一步计算。将当前
val值复制到临时聚合变量中,激活 ID 等于迭代索引的点并将其值加 1,最后将所有点和边导出到表变量,供下一轮迭代使用。''' CREATE OR REPLACE PROCEDURE gv_iter_step(iter INT, nodes TABLE, edges TABLE) AS { VALUE active_set ACTIVE_SET VALUE active_cnt SumAgg<INT> = 0 NODE VALUE next_val SumAgg<INT> = 0 -- 将当前 val 值复制到聚合变量 MATCH (v@Person) PER NODE (v) { SET v.@next_val = v.val } -- 激活 ID 等于迭代索引的点 MATCH (v@Person) WHERE v.id = iter FINALLY { SET active_set = v } -- 将被激活点的值加 1 MATCH (v@Person) WHERE v IN active_set PER NODE (v) { SET v.@next_val = v.val + 1 SET @active_cnt += 1 } -- 导出所有点和边,供下一轮迭代使用 MATCH (v@Person) PER NODE (v) { EXPORT v.id AS id, v.@next_val AS val INTO nodes } MATCH (s@Person)-[e@Link]->(t@Person) PER PATH { EXPORT s.id AS src, t.id AS dst, e.id AS eid INTO edges } LOG_INFO("gv_iter_step iter=", iter, " active_cnt=", @active_cnt) } '''外层迭代过程:驱动整个迭代循环。首先将源临时图中的初始数据导出到表变量并导入图变量,然后在每轮迭代中执行计算、清空图变量、重新导入更新后的数据。
''' CREATE OR REPLACE PROCEDURE gv_iter_outer(max_iter INT) RETURNS (id INT, val INT) AS { GRAPH g TYPED gv_iter_gt TABLE nodes TYPED TABLE {id INT, val INT} TABLE edges TYPED TABLE {src INT, dst INT, eid INT} VALUE iter = 0 -- 从源临时图导出初始数据 MATCH (v@Person) PER NODE (v) { EXPORT v.id AS id, v.val AS val INTO nodes } MATCH (s@Person)-[e@Link]->(t@Person) PER PATH { EXPORT s.id AS src, t.id AS dst, e.id AS eid INTO edges } -- 将初始数据导入图变量 USE g CALL gv_iter_import(nodes, edges) FINISH SET nodes.clear() SET edges.clear() -- 迭代循环 WHILE (iter < max_iter) THEN { USE g CALL gv_iter_step(iter, nodes, edges) FINISH IF (iter <> max_iter - 1) THEN { SET g.clear() USE g CALL gv_iter_import(nodes, edges) FINISH SET nodes.clear() SET edges.clear() } SET iter = iter + 1 } FOR r IN nodes RETURN r.id AS id, r.val AS val ORDER BY r.id } ''' -
执行迭代计算。
在源临时图上调用外层过程,执行 3 轮迭代:
''' USE #gv_iter_base CALL gv_iter_outer(3) RETURN id, val '''返回结果:
+----+-----+ | id | val | +----+-----+ | 0 | 1 | | 1 | 1 | | 2 | 1 | | 3 | 0 | | 4 | 0 | | 5 | 0 | +----+-----+ Log: 2026-03-16T10:14:11.570209 INFO - gv_iter_step iter=0 active_cnt=1 2026-03-16T10:14:11.606670 INFO - gv_iter_step iter=1 active_cnt=1 2026-03-16T10:14:11.634837 INFO - gv_iter_step iter=2 active_cnt=1经过 3 轮迭代,点 0、1、2 分别在第 0、1、2 轮被激活,其
val值从 0 增加到 1。点 3、4、5 未被激活,val值保持为 0。