跳转至
开发版采用单机部署,无需产品 License 文件。需要多机部署或大规模性能测试? 了解企业版

图变量

图变量用于存储子图以进行查询和计算。关键字GRAPH用于定义图变量。

定义图变量有两种方式:

  • 基于图查询:使用 MATCH 语句从现有图中检索子图,并将其存储在图变量中。
  • 基于图类型:使用预定义的图类型声明一个图变量,然后使用 IMPORT 语句向其中导入数据。

前提条件

  • 已创建图。更多信息,请参见 CREATE GRAPH。
  • 具备在当前 Schema 执行MATCH ANY GRAPH操作的权限,或具备在所查询的图上执行MATCH操作的权限。更多信息,请参见角色与权限。

使用说明

  • 不支持通过 DML 修改其中的图数据(如对点、边进行INSERT、DELETE,或使用SET修改点、边属性)。
  • 不能在其上创建索引等结构。
  • 允许执行SET <graph_variable>.clear()用于清空图变量后重新导入数据。

语法

基于查询定义图变量

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 ) , } = GRAPH { use_clause match_statement return_statement }

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
PROPERTY GRAPH graph_variable TYPED graph_type_name

graph_variable_definition_from_type ::=
     'PROPERTY'? 'GRAPH' graph_variable 'TYPED' graph_type_name

清除图变量

graph_variable_clear
SET 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。计算结果导出到表变量后,清空图变量并重新导入更新后的数据,进入下一轮迭代。

  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)
    }
    '''
    
  2. 创建临时图并导入数据。

    创建一个临时图,导入 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。

  3. 创建过程。

    本示例需要三个过程:一个用于将数据导入图变量,一个用于执行单步计算,一个用于驱动外层迭代循环。

    导入过程:将表变量中的点和边数据导入图变量。

    '''
    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
    }
    '''
    
  4. 执行迭代计算。

    在源临时图上调用外层过程,执行 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。