1.创建并使用图空间 : nebula> CREATE SPACE nba (partition_num=10, replica_factor=1); //partition_num:分区数,通常为全集群硬盘数量的 5 倍。 replica_factor:指定集群中副本的数量,通常生产环境为 3,测试环境为 1。
2.指定使用的图空间:nebula> USE nba;
3.查看刚创建的空间:nebula> SHOW SPACES;
4.nebula> CREATE TAG player(name string, age int); //定义数据Schema之顶点标签,形式为标签名称(标签的属性,属性类型)。
5. nebula> CREATE EDGE follow(degree int);//定义数据Schema之边类型,形式为类型名称(边的属性,属性类型)
6.显示定义的顶点标签: nebula> SHOW TAGS;
7.显示定义的边类型:nebula> SHOW EDGES;
8.nebula> DESCRIBE TAG player; //显示player标签的属性
9.nebula> DESCRIBE EDGE follow;获取follow边类型的属性
10.创建索引:nebula> CREATE TAG INDEX player_index_0 on player(name);//在所有标签为player的顶点上为属性name创建了一个索引。
11. nebula> INSERT VERTEX player(name, age) VALUES 102:("LaMar Aldridge", 33); //INSERT VERTEX 语句通过指定点的标签、属性、点 ID 和属性值来插入一个点。
注意:关键词 VALUES 之后的数字是点的 ID(缩写为 VID, int64)。每个图空间中的 VID 必须唯一。
如果一次批量插入同类型的点:nebula> INSERT VERTEX player(name, age) VALUES 100:("Tim Duncan", 42), \ 101:("Tony Parker", 36), 102:("LaMar Aldridge", 33); //反除号 \ 用于实现多行语句。
12.nebula> INSERT EDGE follow(degree) VALUES 100 -> 101:(95); //INSERT EDGE 语句通过指定边类型名称、属性、起始点VID和目标点VID以及属性值来插入边。
一次批量插入多条同类型的边:
nebula> INSERT EDGE follow(degree) VALUES 100 -> 101:(95), 100 -> 102:(90), 102 -> 101:(75);
13.FETCH PROP ON 语句从图空间检索读取数据:
nebula> FETCH PROP ON player 100; //获取点的属性数据,必须指定点的标签和点 VID;
nebula> FETCH PROP ON serve 100 -> 200; //获取边属性数据,必须指定边的类型、起始点 VID 和目标点 VID。
14. 更新点数据:nebula> UPDATE VERTEX 100 SET player.name = "Tim"; //更新点的属性,指定要更新的点 VID,然后在等号右侧为其分配新值来更新点的全部或者部分属性。
15.更新边数据:nebula> UPDATE EDGE 100 -> 101 OF follow SET degree = follow.degree + 1; //更新边的属性,指定边的起始点 VID 和目标点 VID,为其分配新值来更新边的属性。
16. UPSERT 用于插入新的顶点或边或更新现有的顶点或边,若顶点或边不存在,则会新建该顶点或边。UPSERT 是 INSERT 和 UPDATE 的组合。
nebula> UPSERT VERTEX 111 SET player.name = "Dwight Howard", player.age = $^.player.age + 11 WHEN $^.player.name == "Ben Simmons" && $^.player.age > 20 YIELD $^.player.name AS Name, $^.player.age AS Age;
17. 删除点:nebula> DELETE VERTEX 121;//通过指定点 VID 来删除点,同时也会删除该点的所有标签,以及和该点相邻的所有入边和出边。
检查是否删除了该点:nebula> FETCH PROP ON player 121;
18.删除边:nebula> DELETE EDGE follow 100 -> 200; //通过指定边的类型以及起始点 VID 和目标点 VID 来删除边
19. Go&&YIELD使用: nebula> GO FROM 100 OVER follow WHERE $$.player.age >= 35 \ YIELD $$.player.name AS Teammate, $$.player.age AS Age; //查询球员 VID 100 关注的球员,被关注球员年龄需大于 35 岁。 返回其姓名和年龄,并取别名为Teammate和Age。 YIELD 指定希望从查询中返回的结果。$$ 表示边上的目的点。
20. 使用 管道(|) 组合查询:nebula> GO FROM 100 OVER follow YIELD follow._dst AS id | \ GO FROM $-.id OVER serve YIELD $$.team.name AS Team, \ $^.player.name AS Player; //查询球员 100 关注的球员所效力的球队。这里:$^ 表示边的起始点, | 表示管道,$- 表示输入流,上一个查询的输出(id)作为下一个查询的输入($-.id)
21.使用自定义的变量来组合查询:nebula> $var = GO FROM 100 OVER follow YIELD follow._dst AS id; \ GO FROM $var.id OVER serve YIELD $$.team.name AS Team, \ $^.player.name AS Player;
22.如果已为数据创建索引且重构索引,则可用 LOOKUP ON 进行属性查询。
nebula> LOOKUP ON player WHERE player.name == "Tony Parker" \ YIELD player.name, player.age;
23.批量执行,将所有语句放入一个 .ngql 文件中,在服务器端 $ cat schema.ngql | ./bin/nebula -u <user> -p <password>
Nebula Graph支持两种类型的索引:Tag 索引和Edge Type 索引。多数图查询都从拥有共同属性的同一类型的点或边开始遍历,schema 索引使得这些全局检索操作在大型图上更为高效,CREATE INDEX 用于为已有 Tag/Edge-type 创建索引。语法:CREATE {TAG | EDGE} INDEX [IF NOT EXISTS] <index_name> ON {<tag_name> | <edge_name>} (prop_name_list)
24.创建点的单属性索引 nebula> CREATE TAG INDEX player_index_0 on player(name); //在所有标签为player的顶点上为属性name创建一索引。
25. 创建边的单属性索引:nebula> CREATE EDGE INDEX follow_index_0 on follow(degree); //在follow边类型的所有边上为属性degree创建了一索引。
26.nebula> CREATE TAG INDEX player_index_1 on player(name,age); //在所有标签为player的顶点上为属性name和age创建一组合索引。
schema 索引支持为相同 tag 或 edge 中的多个属性同时创建索引,即组合索引,但目前尚不支持跨多个 tag 创建复合索引。
27.列出索引 SHOW {TAG | EDGE} INDEXES
28.nebula> DESCRIBE TAG INDEX player_index_0; //返回索引信息 DESCRIBE {TAG | EDGE} INDEX <index_name>
29.nebula> DROP TAG INDEX player_index_0; //删除索引DROP {TAG | EDGE} INDEX [IF EXISTS] <index_name>
30. 重构索引 REBUILD {TAG | EDGE} INDEX <index_name> [OFFLINE]
如果创建索引时,数据库里已经存有数据,则不会自动对旧的数据进行索引,此时需要对整个图中与索引相关的数据执行索引重构操作以保证索引包含了之前的数据。若当前数据库没有对外提供服务,则可在索引重构时使用 OFFLINE 关键字加快重构速度。 使用 SHOW {TAG | EDGE} INDEX STATUS 命令查看索引是否重构成功。
nebula> REBUILD TAG INDEX single_person_index OFFLINE;
31.LOOKUP 用于寻找指定过滤条件的点或边的集合, WHERE 子句用于向条件中添加过滤性的谓词对数据进行过滤。在使用 LOOKUP 语句之前,请确保已创建索引。
nebula> LOOKUP ON player WHERE player.name== "Kobe Bryant" YIELD player.name AS name | \
GO FROM $-.VertexID OVER serve YIELD $-.name, serve.start_year, serve.end_year, $$.team.name;
32. YIELD 关键词可以在 FETCH、GO 语句中作为子句使用,也可以在 PIPE(|) 中作为独立的语句使用,同时可以作为用于计算的单句使用,可以用于引用变量。对于那些不支持 YIELD 子句的语句,可以使用 YIELD 语句作为一个工具,控制输出。
nebula> $var1 = GO FROM 101 OVER follow; $var2 = GO FROM 105 OVER follow; YIELD $var1.* UNION YIELD $var2.*;
nebula> YIELD hash("Tim") % 100;
33. GO 的用法与 SQL 中的 SELECT 类似,重要区别是 GO 必须从遍历一系列的节点开始。
nebula> GO 2 STEPS FROM 103 OVER follow; /*返回点 103 的 2 度的好友 */
nebula> GO FROM 100,102 OVER serve \
YIELD DISTINCT $$.team.name AS team_name, /* DISTINCT与 SQL 用法相同 */ \
$^.player.name AS player_name; /*起点 (player) 属性 */
34. GO 沿着多边遍历:GO FROM <node_list> OVER <edge_type_list> YIELD [DISTINCT] <return_list>
如:nebula> GO FROM <node_list> OVER edge1, edge2.... //沿着 edge1 和 edge2 遍历
nebula> GO FROM OVER * //这里 * 意味着沿着任意类型的边遍历
注:当沿着多类型边遍历时,对于使用过滤条件有特别限制(也即 WHERE 语句),比如 WHERE edge1.prop1 > edge2.prop2 这种过滤条件是不支持的。
nebula> GO FROM 100 OVER follow, serve YIELD follow.degree, serve.start_year;
返回结果中没有的属性当前会填充默认值, 数值型的默认值为 0, 字符型的默认值为空字符串。bool 类型默认值为 false,timestamp 类型默认值为 0。注意结果中无法分辨每一行属于哪条边,未来版本会在结果中把 edge type 表示出来。
35. REVERSELY 进行反向遍历:nebula> GO FROM 100 OVER follow REVERSELY YIELD follow._src; -- 返回 100
nebula> GO FROM 100 OVER follow REVERSELY YIELD follow._dst AS id | \
GO FROM $-.id OVER serve WHERE $^.player.age > 20 YIELD $^.player.name AS FriendOf, $$.team.name AS Team; //遍历所有关注 100 号球员的球员,找出这些球员服役的球队,筛选年龄大于 20 岁的球员并返回这些球员姓名和其服役的球队名称。如果此处不指定 YIELD,则默认返回每条边目标点的 vid。
36. BIDIRECT 双向遍历
nebula> GO FROM 102 OVER follow BIDIRECT;//同时返回 102 关注的球员及关注 102 的球员
37. 遍历 M 到 N 跳:
nebula> GO 2 TO 4 STEPS FROM 100 OVER follow REVERSELY YIELD DISTINCT follow._dst;//反向遍历从点 100 出发沿 follow 边 2 至 4 跳的点
nebula> GO 4 TO 5 STEPS FROM 101 OVER follow BIDIRECT YIELD DISTINCT follow._dst;//双向遍历从点 101 出发沿 follow 边 4 至 5 跳的点
38. Return 语句用于返回条件成立时的结果。如果条件不成立,则无返回结果。
nebula> $A = GO FROM 100 OVER follow YIELD follow._dst AS dst; \ $rA = YIELD $A.* WHERE $A.dst == 101; \
RETURN $rA IF $rA is NOT NULL; \ /* $rA为非空,返回 $rA */
GO FROM $A.dst OVER follow; /*如果RETURN 语句返回了结果,所以GO FROM 语句不执行,否则执行 */
39. DROP EDGE [IF EXISTS] <edge_type_name>
注: 删除边时Nebula Graph将判断相应边是否有关联的索引,如果有则拒绝删除。此操作将移除指定类型的所有边。此操作仅删除 Schema 信息,硬盘中所有文件及目录均未被直接删除,数据会在下次 compaction 时删除。
40. DROP TAG [IF EXISTS] <tag_name>
注: 删除标签时Nebula Graph将判断相应标签是否有关联的索引,如果有则拒绝删除。 一个节点可以有一个或多个标签(类型)。删除所有标签后,节点将不可访问,同时与节点连接的边也不可使用。删除单个标签后,节点仍可访问,但是已删除标签的属性不可访问。此操作仅删除 Schema 信息,硬盘中所有文件及目录均未被直接删除,数据会在下次 compaction 时删除。
41. DROP SPACE [IF EXISTS] <space_name>
仅支持有 DROP 权限的用户进行此操作。DROP SPACE 将删除指定 space 内的所有内容,其他 space 不受影响。该语句不会立即删除存储引擎中的所有文件和目录(并释放磁盘空间)。删除操作取决于不同存储引擎的实现。
42. Nebula Graph支持TTL,在一定时间后自动从数据库中删除点或者边。过期数据会在下次 compaction 时被删除,在下次 compaction 前,query 会过滤掉过期的点和边。
ttl 功能需要 ttl_col 和 ttl_duration 一起使用。自从 ttl_col 指定的字段的值起,经过 ttl_duration 指定的秒数后,该条数据过期。ttl_duration 单位为秒,范围为 0 ~ max(int64),当 ttl_duration 被设置为 0,则点的此 tag 属性不会过期。
当该条数据有多个 tag,每个 tag 的 ttl 单独处理。
43.对已经创建的 tag,设置 TTL。nebula> CREATE TAG t1(a timestamp);
nebula> ALTER TAG t1 ttl_col = "a", ttl_duration = 5; -- 创建 ttl
nebula> INSERT VERTEX t1(a) values 101:(now());
点 101 的 TAG t1 属性会在 now() 之后,经过 5s 后过期。
44.在创建 tag 时设置 TTL: nebula> CREATE TAG t2(a int, b int, c string) ttl_duration= 100, ttl_col = "a";
nebula> INSERT VERTEX t2(a, b, c) values 102:(1584441231, 30, "Word");
45.删除 TTL,可以设置 ttl_col 字段为空,或删除配置的 ttl_col 字段,或者设置 ttl_duration 为 0。
nebula> ALTER TAG t1 ttl_col = ""; -- drop ttl attribute;
删除配置的 ttl_col 字段:
nebula> ALTER TAG t1 DROP (a); -- drop ttl_col
设置 ttl_duration 为 0:
nebula> ALTER TAG t1 ttl_duration = 0; -- keep the ttl but the data never expires
使用注意
如果 ttl_col 值为非空,则不支持对 ttl_col 值指定的列进行更改操作。
nebula> CREATE TAG t1(a int, b int, c string) ttl_duration = 100, ttl_col = "a";
nebula> ALTER TAG t1 CHANGE (a string); -- failed
46. tag 或 edge 不能同时拥有 TTL 和索引,只能二者择其一,即使 ttl_col 配置的字段与要创建索引的字段不同
nebula> CREATE TAG t1(a int, b int, c string) ttl_duration = 100, ttl_col = "a";
nebula> CREATE TAG INDEX id1 ON t1(a); -- failed
nebula> CREATE TAG t1(a int, b int, c string) ttl_duration = 100, ttl_col = "a";
nebula> CREATE TAG INDEX id1 ON t1(b); -- failed
nebula> CREATE TAG t1(a int, b int, c string);
nebula> CREATE TAG INDEX id1 ON t1(a);
nebula> ALTER TAG t1 ttl_col = "a", ttl_duration = 100; -- failed
对 edge 配置 TTL 与 tag 类似
47. 引用起点的属性: $^.tag_name.prop_name //其中符号 $^ 用于获取起点属性,tag_name 表示起点的 tag,prop_name 为指定属性的名称。
48. 引用终点的属性: $$.tag_name.prop_name //. $$ 用于获取终点属性,tag_name 表示终点的 tag,prop_name 为指定属性的名称。
nebula> GO FROM 100 OVER follow YIELD $^.player.name AS startName, $$.player.age AS endAge; //获取起点的属性名称和终点的属性年龄。
49. 获取边属性:edge_type.edge_prop //edge_type为边的类型,edge_prop为属性:
nebula> GO FROM 100 OVER follow YIELD follow.degree;
50. 一条边有四个内置属性:_src: 边起点 ID、 _dst: 边终点 ID、 _type: 边类型、 _rank: 边的 rank 值。获取起点和终点 ID 可通过 _src 和 _dst 获取,这在显示图路径时会用到。
nebula> GO FROM 100 OVER follow YIELD follow._src, follow._dst, follow._type, follow._rank; //通过引用 follow._src 作为起点 ID 和 follow._dst 作为终点 ID,返回起点 100 follow 的所有邻居节点。其中 follow._src 返回起点 ID,follow._dst 返回终点 ID。
51. FIND PATH 语法用于获取最短路径及全路径。SHORTEST 寻找最短路径关键词。ALL 寻找全路径关键词。
FIND SHORTEST | ALL PATH FROM <vertex_id_list> TO <vertex_id_list> OVER <edge_type_list> [UPTO <N> STEPS]
<vertex_id_list>::=[vertex_id [, vertex_id]] 为节点列表,用逗号隔开。支持输入 $- 及变量 $var。
<edge_type_list> 指定边的类型,多种边类型用 , 隔开,用 * 表示所有边类型。 <N> 为跳数,默认值 5。
注意:当起点及终点是 ID 列表时,表示寻找从任意起点开始到终点的最短路径。全路径会有环,路径显示方式为 id <edge_name, rank> id。
nebula> FIND SHORTEST PATH FROM 100 to 200 OVER *;
nebula> FIND ALL PATH FROM 100 to 200 OVER *;