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

GQL 入门:创建图并完成增删改查

本文在悦数图管理控制台中创建一张练习图,演示如何用 GQL 定义图结构、写入数据、查询关系、更新属性和删除数据。练习中会创建两个表示人的点 Alice 和 Bob,以及一条从 Alice 指向 Bob 的“认识”关系。

开始前

先以root登录悦数图管理,再在顶部导航栏中单击控制台。使用其他客户端时,见使用 ngql 或内置网页控制台。本文无需加载movie示例数据集。

本文将新建图类型gql_practice_type和图gql_practice,这两个名称应尚未被使用。再次完整练习时,按重新练习更换名称。

按顺序逐个执行代码块:将语句粘贴到查询编辑器,单击运行按钮;成功后,将编辑器中的内容替换为下一条语句。结果表以悦数图管理的表格视图为例,字符串显示在双引号中。

1. 定义图结构

图类型定义图中允许有哪些点、边和属性;图保存符合该类型的数据。本次练习使用以下结构:

元素 类型 属性 说明
点 Person id、name、age 在图中用id唯一区分Person点
边 Knows since 从一个Person指向另一个Person,since表示认识的年份

本文使用默认 Schema/default_schema。Schema 类似文件夹,用于组织图类型和图。

切换回默认 Schema

如果此前在控制台中切换过 Schema,先执行以下语句,再继续创建图类型:

SESSION SET SCHEMA /default_schema

执行以下语句,创建图类型gql_practice_type:

CREATE GRAPH TYPE gql_practice_type AS {
  NODE Person (LABEL Person {id INT64 PRIMARY KEY, name STRING, age INT32}),
  EDGE Knows (Person)-[:Knows {since INT32}]->(Person)
}

语句中各部分的含义:

  • NODE Person定义点类型,EDGE Knows定义边类型。
  • INT64和INT32是整数类型,STRING是字符串类型。
  • PRIMARY KEY将id指定为主键。同一图中,两个Person点不能使用相同的id。
  • LABEL Person和:Knows分别定义点和边的标签。本例中,类型和标签使用相同名称。

更多解释见图数据基本概念。

使用 ngql 或内置网页控制台

按ngql连接步骤或内置网页控制台连接步骤连接悦数图数据库开发版。只需完成连接,无需加载示例数据;连接后在同一客户端中依次执行本文语句。

在ngql中,多行语句首尾各用一行'''包围。例如,创建图类型时输入:

'''
CREATE GRAPH TYPE gql_practice_type AS {
  NODE Person (LABEL Person {id INT64 PRIMARY KEY, name STRING, age INT32}),
  EDGE Knows (Person)-[:Knows {since INT32}]->(Person)
}
'''

输入末尾的'''并按 Enter 后提交。本文其余多行语句也使用相同方式。ngql默认表格中的 Alice、Bob 等字符串不带双引号,属性值与本文结果表相同。

在内置网页控制台中,多行语句可直接粘贴到编辑器,并单击运行按钮执行。

2. 创建并选择图

基于刚才的图类型创建练习图:

CREATE GRAPH gql_practice TYPED gql_practice_type

将它设置为当前会话的工作图,后续读写语句就会访问这张图:

SESSION SET GRAPH gql_practice
重新连接或为单条语句指定图

重新连接或切换客户端后,需要在新会话中再次执行SESSION SET GRAPH gql_practice。

也可以在单条读写语句的开头用USE指定图,例如:

USE gql_practice
MATCH (p@Person)
RETURN p.name

USE只对所在语句生效,不更改会话工作图。更多信息见 USE。

3. 插入点和边

先插入 Alice 和 Bob。以下插入语句各执行一次,每个代码块单独运行:

INSERT (p@Person {id: 1, name: "Alice", age: 30})
INSERT (p@Person {id: 2, name: "Bob", age: 28})

@Person指定点类型,花括号中是属性及其值。p是语句中的变量名,后续语句可以使用其他变量名引用同一个点。

再找到这两个已存在的点,在它们之间插入一条边:

MATCH (a@Person {id: 1}), (b@Person {id: 2})
INSERT (a)-[r@Knows {since: 2024}]->(b)

MATCH按主键找到 Alice 和 Bob,分别绑定到变量a和b。INSERT使用这两个点创建Knows边;箭头表示边从 Alice 指向 Bob。

重复插入数据

请勿重复执行已经成功的插入语句。相同主键的点或相同起点、终点的Knows边已存在时,普通INSERT会报冲突错误。其他冲突处理方式见 INSERT。

4. 查询点和关系

查看图中的人

MATCH (p@Person)
RETURN p.id AS id, p.name AS name, p.age AS age
ORDER BY id

预期结果:

id name age
1 "Alice" 30
2 "Bob" 28

MATCH (p@Person)匹配所有Person点。RETURN选择结果列,AS为列命名,ORDER BY id按编号排序。

按属性筛选

查询年龄大于 28 岁的人,使用WHERE指定筛选条件:

MATCH (p@Person)
WHERE p.age > 28
RETURN p.name AS name, p.age AS age

预期结果:

name age
"Alice" 30

沿关系查找

查询 Alice 认识谁,以及从哪一年开始认识:

MATCH (a@Person {id: 1})-[r@Knows]->(b@Person)
RETURN a.name AS person,
       b.name AS friend,
       r.since AS known_since

预期结果:

person friend known_since
"Alice" "Bob" 2024

圆括号表示点,方括号表示边。变量r引用这条边,可以用r.since读取边的属性。这个模式从 Alice 出发,沿Knows边的方向查找目标点。

5. 更新属性

将 Alice 的年龄改为31:

MATCH (p@Person {id: 1})
SET p.age = 31

MATCH定位要修改的点,SET为属性赋新值。更新后重新查询:

MATCH (p@Person {id: 1})
RETURN p.name AS name, p.age AS age

预期结果:

name age
"Alice" 31

再将 Alice 和 Bob 开始认识的年份改为2023:

MATCH (a@Person {id: 1})-[r@Knows]->(b@Person {id: 2})
SET r.since = 2023

再次运行关系查询时,known_since应为2023。主键属性id不支持通过SET修改。

6. 删除边和点

先删除 Alice 到 Bob 的Knows边:

MATCH (a@Person {id: 1})-[r@Knows]->(b@Person {id: 2})
DELETE r

再次运行关系查询,应不再返回这条关系。删除边后,Alice 和 Bob 两个点仍然存在。

再删除 Alice。普通DELETE只能删除没有连接边的点,因此需要先执行上面的删边操作:

MATCH (p@Person {id: 1})
DELETE p

检查剩余点:

MATCH (p@Person)
RETURN p.id AS id, p.name AS name, p.age AS age
ORDER BY id

此时应只返回 Bob:

id name age
2 "Bob" 28

图gql_practice和图类型gql_practice_type仍然保留。

同时删除点及其连接的边

如果 Alice 和这条边仍然存在,可以用以下一条语句替代本节的两个删除步骤。已完成上述删除操作时,无需再执行:

MATCH (p@Person {id: 1})
DETACH DELETE p

DETACH DELETE删除 Alice 及其所有连接的边,并保留 Bob。

重新练习

再次完整练习时,换用尚未使用的图类型和图名称。例如,在本文所有语句中统一替换以下名称,再从第 1 步开始:

原名称 再次练习时使用的名称
gql_practice_type gql_practice_type_2
gql_practice gql_practice_2

只需查询已有练习图时,先执行SESSION SET GRAPH gql_practice,再运行查询。数据保留此前修改后的状态;完成本文的删除步骤后,图中只剩 Bob,不会再返回开头的完整结果。

下一步