文章目录
- 管理Storage主机
- 空间
- 创建标签
- 边
- 点
-
- 增
- 改
- 删除点和边
- 索引
-
- 创建索引
- 重建索引
- drop tag
- 查询
-
- match
- go
- FETCH
- LOOKUP
- 统计
管理Storage主机
从 3.0.0 版本开始,在配置文件中添加的 Storage 主机无法直接读写,配置文件的作用仅仅是将 Storage 主机注册至 Meta 服务中。必须使用ADD
HOSTS 命令后,才能正常读写 Storage 主机。
向集群中增加 Storage 主机。
ADD HOSTS <ip>:<port> [,<ip>:<port> ...];
add hosts 10.199.4.142:9779
请先等待 2 个心跳周期(20 秒),再查看
show hosts
空间
创建空间
create space basketballplayer(
partition_num = 10,
replica_factor = 1,
vid_type = FIXED_STRING(30)
);show spaces;describe space basketballplayer;drop space xxx_space;use basketballplayer;
partition_num 指定图空间的分片数量。建议设置为集群中硬盘数量的 20 倍(HDD 硬盘建议为 2 倍)。例如集群中有 3 个硬盘,建议设置 60 个分片。默认值为 100。
创建标签
create tag player(name string, age int);
create tag team(name string);show tags;describe tag player;create tag proper_free();
边
语法
INSERT EDGE [IF NOT EXISTS] <edge_type> ( <prop_name_list> ) VALUES
<src_vid> -> <dst_vid>[@<rank>] : ( <prop_value_list> )
[, <src_vid> -> <dst_vid>[@<rank>] : ( <prop_value_list> ), ...];
<prop_name_list> ::=
[ <prop_name> [, <prop_name> ] ...]
<prop_value_list> ::=
[ <prop_value> [, <prop_value> ] ...]
create edge follow(degree int);
create edge serve(start_year int , end_year int)
create edge no_proerty()show edges;
describe edge follow;CREATE EDGE IF NOT EXISTS buy(number int);INSERT EDGE follow(degree) VALUES "player101" -> "player100":(95);
INSERT EDGE follow(degree) VALUES "player101" -> "player102":(90);
INSERT EDGE follow(degree) VALUES "player102" -> "player100":(75);
INSERT EDGE serve(start_year, end_year) VALUES "player101" -> "team204":(1999, 2018),"player102" -> "team203":(2006, 2015);fetch prop on follow player101 -> player102, player102 -> player103;
如果在两点之前插入多条同类型表,可以使用ranking参数
# 插入100 到101 rank为1的表
insert edge follow(degree) values 100 -> 101@1:(80)# 查找100 到101 rank为1的表
fetch prop on follow 100 -> 101@1
点
增
语法
INSERT VERTEX [IF NOT EXISTS] [tag_props, [tag_props] ...]
VALUES <vid>: ([prop_value_list])
tag_props:
tag_name ([prop_name_list])
prop_name_list:
[prop_name [, prop_name] ...]
prop_value_list:
[prop_value [, prop_value] ...]
vid 是 Vertex ID 的缩写, vid 在一个图空间中是唯一的
INSERT VERTEX player(name, age) VALUES "player100":("Tim Duncan", 42);
INSERT VERTEX player(name, age) VALUES "player101":("Tony Parker", 36);
INSERT VERTEX player(name, age) VALUES "player102":("LaMarcus Aldridge", 33);
INSERT VERTEX team(name) VALUES "team203":("Trail Blazers"), "team204":("Spurs");
多标签插入
create tag test1(name string);
create tag test2(age int);insert vertex test1(name), test2(age) values 199:("Multitags",33);insert vertex tag1(),tag2() values "m1":(),"m1":()fetch prop on test1 199;
fetch prop on test2 199;
查看插入结果
fetch prop on player player100;fetch prop on player player100, player101, player103;
改
修改点和边
用户可以使用UPDATE 语句或UPSERT 语句修改现有数据。
UPSERT 是UPDATE 和INSERT 的结合体。当使用UPSERT 更新一个点或边,如果它不存在,数据库会自动插入一个新的点或边。
每个 partition 内部, UPSERT 操作是一个串行操作,所以执行速度比执行 INSERT 或 UPDATE 慢很多。其仅在多个 partition 之间有并发。
UPDATE 点
UPDATE VERTEX <vid> SET <properties to be updated>
[WHEN <condition>] [YIELD <columns>];
UPDATE 边
UPDATE EDGE <source vid> -> <destination vid> [@rank] OF <edge_type>
SET <properties to be updated> [WHEN <condition>] [YIELD <columns to be output>];
UPSERT 点或边
UPSERT {VERTEX <vid> | EDGE <edge_type>} SET <update_columns>
[WHEN <condition>] [YIELD <columns>];
用UPDATE 修改 VID 为player100 的球员的name 属性,然后用FETCH 语句检查结果。
nebula> UPDATE VERTEX "player100" SET player.name = "Tim";
nebula> FETCH PROP ON player "player100" YIELD properties(vertex);
+------------------------+
| properties(VERTEX) |
+------------------------+
| {age: 42, name: "Tim"} |
+------------------------+
用UPDATE 修改某条边的degree 属性,然后用FETCH 检查结果。
nebula> UPDATE EDGE "player101" -> "player100" OF follow SET degree = 96;
nebula> FETCH PROP ON follow "player101" -> "player100" YIELD properties(edge);
+------------------+
| properties(EDGE) |
+------------------+
| {degree: 96} |
+------------------+
用INSERT 插入一个 VID 为player111 的点,然后用UPSERT 更新它。
nebula> INSERT VERTEX player(name,age) VALUES "player111":("David West", 38);
nebula> UPSERT VERTEX "player111" SET player.name = "David", player.age = $^.player.age + 11 \
WHEN $^.player.name == "David West" AND $^.player.age > 20 \
YIELD $^.player.name AS Name, $^.player.age AS Age;
+---------+-----+
| Name | Age |
+---------+-----+
| "David" | 49 |
+---------+-----+
删除点和边
删除点
DELETE VERTEX <vid1>[, <vid2>...]
nebula> DELETE VERTEX "player111", "team203";
删除边
DELETE EDGE <edge_type> <src_vid> -> <dst_vid>[@<rank>]
[, <src_vid> -> <dst_vid>...]
nebula> DELETE EDGE follow "player101" -> "team204";
索引
用户可以通过 CREATE INDEX 语句为 Tag 和 Edge type 增加索引。
MATCH 和LOOKUP 语句的执行都依赖索引,但是索引会导致写性能大幅降低(降低 90%甚至更多)。请不要随意在生产环境中使用索引,除非很清楚使用索引
对业务的影响。
必须为“已写入但未构建索引”的数据重建索引,否则无法在MATCH 和LOOKUP 语句中返回这些数据。参见重建索引。
创建索引
CREATE {TAG | EDGE} INDEX [IF NOT EXISTS] <index_name>
ON {
<tag_name> | <edge_name>} ([<prop_name_list>]) [COMMENT = '<comment>'];
# 为变长字符串属性创建索引时,必须用 prop_name(length) 指定索引长度;
# 为 Tag 或 Edge type 本身创建索引时,忽略 <prop_name_list> 。
create edge index serve_index_0 on serve(start_year);rebuild edge index serve_index_0;
重建索引
REBUILD {TAG | EDGE} INDEX <index_name>;
为没有指定长度的变量属性创建索引时,需要指定索引长度。在 utf-8 编码中,一个中文字符占 3 字节,请根据变量属性长度设置合适的索引长度。例如
10 个中文字符,索引长度需要为 30。详情请参见创建索引。
基于索引的LOOKUP 和MATCH 示例
确保LOOKUP 或MATCH 有一个索引可用。如果没有,请先创建索引。
找到 Tag 为player 的点的信息,它的name 属性值为Tony Parker 。
// 为 name 属性创建索引 player_index_1。
nebula> CREATE TAG INDEX IF NOT EXISTS player_index_1 ON player(name(20));
// 重建索引确保能对已存在数据生效。
nebula> REBUILD TAG INDEX player_index_1
+------------+
| New Job Id |
+------------+
| 31 |
+------------+
// 使用 LOOKUP 语句检索点的属性。
nebula> LOOKUP ON player WHERE player.name == "Tony Parker" \
YIELD properties(vertex).name AS name, properties(vertex).age AS age;
+---------------+-----+
| name | age |
+---------------+-----+
| "Tony Parker" | 36 |
+---------------+-----+
// 使用 MATCH 语句检索点的属性。
nebula> MATCH (v:player{name:"Tony Parker"}) RETURN v;
+-----------------------------------------------------+
| v |
+-----------------------------------------------------+
| ("player101" :player{age: 36, name: "Tony Parker"}) |
+-----------------------------------------------------+
drop tag
drop tag member
-1005:Conflict!
一旦标签创建了index直接删除标签就会出现如上错误
# 如果记不清楚具体是什么时可以用
show tag indexes;
DROP {TAG | EDGE} INDEX [IF EXISTS] <index_name>;
DROP TAG INDEX member_index_0;
DROP TAG member;
查询
go from "player100" over follow;
match
语句是查询图数据最常用的,可以灵活的描述各种图模式,但是它依赖索引去匹配 Nebula Graph 中的数据模型,性能也还需要调
语法
MATCH <pattern> [<clause_1>] RETURN <output> [<clause_2>];
match (u:player) return u limit 11;match (e:member:tag2) -->(s1:store) where s1.store.id=="s2" return e,s1 limit 111
go
语句可以根据指定的条件遍历数据库。GO 语句从一个或多个点开始,沿着一条或多条边遍历,返回YIELD 子句中指定的信息
语法
GO [[<M> TO] <N> STEPS ] FROM <vertex_list>
OVER <edge_type_list> [{REVERSELY | BIDIRECT}]
[ WHERE <conditions> ]
YIELD [DISTINCT] <return_list>
[{ SAMPLE <sample_list> | <limit_by_list_clause> }]
[| GROUP BY {
<col_name> | expression> | <position>} YIELD <col_name>]
[| ORDER BY <expression> [{
ASC | DESC}]]
[| LIMIT [<offset>,] <number_rows>];
从vid 为player_100 开始,遍历所有被vid关注的点
go from player_100 over follow;
返回vid 为player_100 关注并且球员年龄大于35
go from 100 over follow where $$.player.age > 35 yield $$.player.name as teammate, $$player.age as Age;
返回vid 为player_100 所效忠的球队
go from 100 over follow yield follow._dst as id |
go from $-.id over serve yield $$.team.name as Team, $^.player.name as Player;# 方法2^
$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;
# 从 VID 为Aemon-Targaryen-(Dragonknight)开始,沿着边relation 找到连接的人
go from "Aemon-Targaryen-(Dragonknight)" over relation yield id($$);# 从 VID 为player101 的球员开始,沿着边follow 查找年龄大于或等于 35 岁的球员,并返回他们的姓名和年龄,同时重命名对应的列
GO FROM "player101" OVER follow WHERE properties($$).age >= 35
YIELD properties($$).name AS Teammate, properties($$).age AS Age;
从 VID 为player101 的球员开始,沿着边follow 查找连接的球员,然后检索这些球员的球队。为了合并这两个查询请求,可以使用管道符或临时变
量。
使用管道符
nebula> GO FROM "player101" OVER follow YIELD dst(edge) AS id | \
GO FROM $-.id OVER serve YIELD properties($$).name AS Team, \
properties($^).name AS Player;
+-----------------+---------------------+
| Team | Player |
+-----------------+---------------------+
| "Spurs" | "Tim Duncan" |
| "Trail Blazers" | "LaMarcus Aldridge" |
| "Spurs" | "LaMarcus Aldridge" |
| "Spurs" | "Manu Ginobili" |
+-----------------+---------------------+
使用临时变量
当复合语句作为一个整体提交给服务器时,其中的临时变量会在语句结束时被释放。
nebula> $var = GO FROM "player101" OVER follow YIELD dst(edge) AS id; \
GO FROM $var.id OVER serve YIELD properties($$).name AS Team, \
properties($^).name AS Player;
+-----------------+---------------------+
| Team | Player |
+-----------------+---------------------+
| "Spurs" | "Tim Duncan" |
| "Trail Blazers" | "LaMarcus Aldridge" |
| "Spurs" | "LaMarcus Aldridge" |
| "Spurs" | "Manu Ginobili" |
+-----------------+---------------------+
FETCH
可以获得点或边的属性
查询 Tag 属性
语法
FETCH PROP ON {
<tag_name>[, tag_name ...] | *}
<vid> [, vid ...]
YIELD <return_list> [AS <alias>];
查询边属性
语法
FETCH PROP ON <edge_type> <src_vid> -> <dst_vid>[@<rank>] [, <src_vid> -> <dst_vid> ...]
YIELD <output>;
LOOKUP
是基于索引的,和WHERE 子句一起使用,查找符合特定条件的数据。
LOOKUP ON {
<vertex_tag> | <edge_type>}
[WHERE <expression> [AND <expression> ...]]
YIELD <return_list> [AS <alias>];
<return_list>
<prop_name> [AS <col_alias>] [, <prop_name> [AS <prop_alias>] ...];
统计
submit job stats;
show job 248show stats;
match (e:member) with e limit 10000000 return count(*)