一、Nebula Graph简介
Nebula Graph是一款开源的、分布式的、易扩展的原生图数据库,能够承载数千亿个点和数万亿条边的超大规模数据集,并且提供毫秒级查询。
二、什么是图数据库
图数据库是专门存储庞大的图形网络并从中检索信息的数据库。它可以将图中的数据高效存储为点(vertex)和边(edge),还可以将属性(property)附加到点和边上。
图数据库适合存储大多数从现实抽象出的数据类型。世界上几乎所有领域的事物都有内在联系,像关系型数据库这样的建模系统会提取实体之间的关系,并将关系单独存储到表和列中,而实体的类型和属性存储在其他列甚至其他表中,这使得数据管理费时费力。
Nebula Graph作为一个典型的原
生图数据库,允许将丰富的关系存储为边,边的类型和属性可以直接附加到边上。
三、Nebula Graph的优势
3.1 开源
Nebula Graph是在Apache 2.0和Commons Clause 1.0条款下开发的。越来越多的人,如数据库开发人员、数据科学家、安全专家、算法工程师,都参与到Nebula Graph的设计和开发中来。
3.2 高性能
基于图数据库的特性使用C++编写的Nebula Graph,可以提供毫秒级查询。众多数据库中,Nebula Graph在图数据服务领域展现了卓越的性能,数据规模越大,Nebula Graph优势就越大。
3.3 易扩展
Nebula Graph采用shared-nothing架构,支持在不停止数据库服务的情况下扩缩容。
3.4 易开发
Nebula Graph提供Java、Python、C++和Go等流行编程语言的客户端,更多客户端仍在开发中。
3.5 高可靠访问控制
Nebula Graph支持严格的角色访问控制和LDAP(Lightweight Directory Access Protocol)等外部认证服务,能够有效提高数据安全性。
3.6 生态多样化
Nebula Graph开放了越来越多的原生工具,例如Nebula Graph Studio、Nebula Console、Nebula Exchange等。
此外,Nebula Graph还具备与Spark、Flink、HBase等产品整合的能力。
3.7 兼容openCypher查询语言
Nebula Graph查询语言,也称为nGQL(Nebula Graph Query Language),是一种声明性的、兼容openCypher的文本查询语言,易于理解和使用。
用户可以在Nebula Graph GitHub的features目录内查看超过2500条nGQL示例。features目录内包含很多.features格式的文件,每个文件都记录了使用nGQL的场景和示例。
3.8 灵活数据建模
用户可以轻松地在Nebula Graph中建立数据模型,不必将数据强制转换为关系表。而且可以自由增加、更新和删除属性。
四、适用场景
Nebula Graph可用于各种基于图的业务场景。为节约转换各类数据到关系型数据库的时间,以及避免复杂查询,建议使用Nebula Graph。
4.1 欺诈检测
金融机构必须仔细研究大量的交易信息,才能检测出潜在的金融欺诈行为,并了解某个欺诈行为和设备的内在关联。这种场景可以通过图来建模,然后借助Nebula Graph,可以很容易地检测出诈骗团伙或其他复杂诈骗行为。
4.2 实时推荐
Nebula Graph能够及时处理访问者产生的实时信息,并且精准推送文章、视频、产品和服务。
4.3 知识图谱
自然语言可以转化为知识图谱,存储在Nebula Graph中。用自然语言组织的问题可以通过智能问答系统中的语义解析器进行解析并重新组织,然后从知识图谱中检索出问题的可能答案,提供给提问人。
4.4 社交网络
人际关系信息是典型的图数据,Nebula Graph可以轻松处理数十亿人和数万亿人际关系的社交网络信息,并在海量并发的情况下,提供快速的好友推荐和工作岗位查询。
五、数据结构
Nebula Graph数据模型使用6种基本的数据结构
5.1 图空间(space)
图空间用于隔离不同团队或者项目的数据。不同图空间的数据是相互隔离的,可以指定不同的存储副本数、权限、分片等。
CREATE SPACE IF NOT EXISTS ac_test_space (partition_num = 10, replica_factor = 1, charset = utf8, collate = utf8_bin, vid_type = INT64);
Storage服务使用Raft协议(多数表决),为保证可用性,要求出故障的副本数量不能达到一半。如果replica_factor=2,当其中一个副本故障时,就会导致系统无法工作;如果replica_factor=4,只能有一个副本可以出现故障,这和replica_factor=3是一样。以此类推,所以replica_factor设置为奇数即可。建议在生产环境中设置replica_factor=3,测试环境中设置replica_factor=1,不要使用偶数。
5.2 点(vertex)
点用来保存实体对象,特点如下:
1、点是用点标识符(VID)标识的。VID在同一图空间中唯一。VID 是一个 int64, 或者 fixed_string(N)。
2、点必须有至少一个标签(Tag),也可以有多个标签。
5.3 边(edge)
边是用来连接点的,表示两个点之间的关系或行为,特点如下:
1、两点之间可以有多条边。
2、边是有方向的,不存在无向边。
3、四元组 <起点VID、边类型(edge type)、边排序值(rank)、终点VID> 用于唯一标识一条边。边没有EID。
4、一条边有且仅有一个边类型。
5、一条边有且仅有一个 rank。其为int64, 默认为0。
//创建关注关系边
CREATE EDGE IF NOT EXISTS focusEdge(relation string);
//创建好友关系边
CREATE EDGE IF NOT EXISTS friendsEdge(relation string);
5.4 标签(tag)
标签由一组事先预定义的属性构成。
//创建会员Tag
CREATE TAG IF NOT EXISTS memberTag(id int, mobile string,nickName string,markId string,iconUrl string,sex string,type string);
//创建好友群Tag
CREATE TAG IF NOT EXISTS friendsGroupTag(groupName string);
5.5 边类型(edge type)
边类型由一组事先预定义的属性构成。
5.6 属性(properties)
属性是指以键值对(key-value pair)形式存储的信息。
六、有向属性图
Nebula Graph使用有向属性图模型,指点和边构成的图,这些边是有方向的,点和边都可以有属性。
下表为篮球运动员数据集的结构示例,包括两种类型的点(player、team)和两种类型的边(serve、follow)。
七、图数据库概念介绍
7.1 运动员表
Joe和Foesa两个都是运动员,表示为:
使用SQL语句创建
create database home;
use home;
create table player(
id int primary key,
name varchar(255),
age int,
start_year int,
end_year int
);
insert into player(id,name,age,start_year,end_year) values(101,'Joe',19,2015,2021);
使用Nebula Graph创建
create space home(partition_num-15,replica_factor=1,vid_type=INT64);
use home;
create TAG player(
name string,
age int,
start_year_int,
end_year int
);
insert vertex player(name,age,start_year,end_year) values 101:("Joe",20,2015,2021)
7.2 学生表
对了,Joe是个运动员,同时也是一名学生,他在student表中,但Foesa已经毕业已经不是一个学生了,不在student表中,表示为:
这里的player表和student表相当于nGQL中的TAG(标签)。对于Joe来说,不同的身份,意味着他有不同的标签。而player表中的name、age、start_year、end_year、都是标签player的属性。
7.3 insert会覆盖之前的数据
在Nebula Graph中执行
insert vertex player(name,age,start_year,end_year) values 101:("Joe",20,2013,2021)
由于101已经在Nebula Graph存在了,再次执行insert并不会报错,而是覆盖之前的数据,以最新的插入为准。
7.4 边(一种关系)
平时Joe会和Foesa打电话,我们可以为Joe和Foesa的通话这一关系建立一个名为call的边。
CREATE EDGE call(id1 string,id2 string,rank int , time data,continue_time int);
- 在call表中的time和continue_time就是边类型的属性,它们有着不同的数据类型。
- 需要注意的是,每个图空间的边类型名称不能重复,名称设置后无法修改。
- 我们可以看到,起始点为101,目的点为102,边类型都为call的三条边
- id1+id2+rank类似于sql中的联合主键,因此我们可以使用:边类型、起始点、目的点、rank 四个唯一确定一条边。
八、Nebula Graph安装
九、常用语法(CRUD)
9.1 图空间和Schema
一个Nebula Graph实例由一个或多个图空间组成。每个图空间都是物理隔离的,用户可以在同一个实例中使用不同的图空间存储不同的数据集。
为了在图空间中插入数据,需要为图数据库定义一个Schema。Nebula Graph的Schema是由如下几部分组成。
9.2 检查Nebula Graph集群的机器状态
首先建议检查机器状态,确保所有的Storage服务连接到了Meta服务。执行命令SHOW HOSTS
查看机器状态。
nebula> SHOW HOSTS;
+-------------+-----------+-----------+--------------+----------------------+------------------------+
| Host | Port | Status | Leader count | Leader distribution | Partition distribution |
+-------------+-----------+-----------+--------------+----------------------+------------------------+
| "storaged0" | 9779 | "ONLINE" | 0 | "No valid partition" | "No valid partition" |
+-------------+-----------+-----------+--------------+----------------------+------------------------+
| "storaged1" | 9779 | "ONLINE" | 0 | "No valid partition" | "No valid partition" |
+-------------+-----------+-----------+--------------+----------------------+------------------------+
| "storaged2" | 9779 | "ONLINE" | 0 | "No valid partition" | "No valid partition" |
+-------------+-----------+-----------+--------------+----------------------+------------------------+
| "Total" | __EMPTY__ | __EMPTY__ | 0 | __EMPTY__ | __EMPTY__ |
+-------------+-----------+-----------+--------------+----------------------+------------------------+
Got 4 rows (time spent 1061/2251 us)
9.3 异步实现创建和修改
Nebula Graph中执行如下创建和修改操作,是异步实现的,需要在下一个心跳周期才同步数据。
- CREATE SPACE
- CREATE TAG
- CREATE EDGE
- ALTER TAG
- ALTER EDGE
- CREATE TAG INDEX
- CREATE EDGE INDEX
默认心跳周期是10秒。修改心跳周期参数heartbeat_interval_secs。为确保数据同步,后续操作能顺利进行,可采取以下方法之一:
执行SHOW或DESCRIBE命令检查相应对象的状态,确保创建或修改已完成。如果没有完成,请等待几秒重试。
等待2个心跳周期(20秒)。
9.4 创建和选择图空间
9.4.1 创建图空间nGQL语法
CREATE SPACE [IF NOT EXISTS] <graph_space_name>
[(partition_num = <partition_number>,
replica_factor = <replica_number>,
vid_type = {FIXED_STRING(<N>) | INT64})];
示例
nebula> CREATE SPACE basketballplayer(partition_num=15, replica_factor=1, vid_type=fixed_string(30));
重点:
创建图空间时,要选择VID的数据类型,vid_type
fixed_string <N>:定长字符串,长度为N,不足时会填充,超出长度会报错
int64:64位整数每个图空间仅支持一种VID数据类型
选择好VID的类型后,不能修改
9.4.2 列出创建成功的图空间
nebula> SHOW SPACES;
9.4.3 选择数据库
USE <graph_space_name>;
9.5 创建标签和边类型
nGQL语法
CREATE {TAG | EDGE} {<tag_name> | <edge_type>}(<property_name> <data_type>
[, <property_name> <data_type> ...]);
示例
nebula> CREATE TAG player(name string, age int);
nebula> CREATE EDGE follow(degree int);
9.6 插入点和边
用户可以使用INSERT语句,基于现有的标签插入点,或者基于现有的边类型插入边。
插入点nGQL语法
INSERT VERTEX <tag_name> (<property_name>[, <property_name>...])
[, <tag_name> (<property_name>[, <property_name>...]), ...]
{VALUES | VALUE} <vid>: (<property_value>[, <property_value>...])
[, <vid>: (<property_value>[, <property_value>...];
VID是Vertex ID的缩写,VID在一个图空间中是唯一的。
插入边nGQL语法
INSERT EDGE <edge_type> (<property_name>[, <property_name>...])
{VALUES | VALUE} <src_vid> -> <dst_vid>[@<rank>] : (<property_value>[, <property_value>...])
[, <src_vid> -> <dst_vid>[@<rank>] : (<property_name>[, <property_name>...]), ...];
示例
nebula> INSERT VERTEX player(name, age) VALUES "player100":("Tim Duncan", 42);
nebula> INSERT EDGE follow(degree) VALUES "player100" -> "player101":(95);
9.7 查询数据
GO语句可以根据指定的条件遍历数据库。GO语句从一个或多个点开始,沿着一条或多条边遍历,返回YIELD子句中指定的信息。
FETCH语句可以获得点或边的属性。
LOOKUP语句是基于索引的,和WHERE子句一起使用,查找符合特定条件的数据。
MATCH语句是查询图数据最常用的,但是它依赖索引去匹配Nebula Graph中的数据模型。
9.7.1 GO语句示例
从VID为player100的球员开始,沿着边follow找到连接的球员。
nebula> GO FROM "player100" OVER follow;
+-------------+
| follow._dst |
+-------------+
| "player101" |
+-------------+
| "player102" |
+-------------+
从VID为player100的球员开始,沿着边follow查找年龄大于或等于35岁的球员,并返回他们的姓名和年龄,同时重命名对应的列。
nebula> GO FROM "player100" OVER follow WHERE $$.player.age >= 35 \
-> YIELD $$.player.name AS Teammate, $$.player.age AS Age;
+---------------+-----+
| Teammate | Age |
+---------------+-----+
| "Tony Parker" | 36 |
+---------------+-----+
从VID为player100的球员开始,沿着边follow查找连接的球员,然后检索这些球员的球队。为了合并这两个查询请求,可以使用管道符或临时变量。
使用管道
nebula> GO FROM "player100" OVER follow YIELD follow._dst AS id | \
GO FROM $-.id OVER serve YIELD $$.team.name AS Team, \
$^.player.name AS Player;
+-----------+---------------+
| Team | Player |
+-----------+---------------+
| "Nuggets" | "Tony Parker" |
+-----------+---------------+
用户可以使用YIELD显式声明需要返回的结果,如果不使用YIELD,默认返回目标点ID。
必须在YIELD子句中为需要的返回结果设置别名,才能在管道符右侧使用引用符$-
,例如示例中的$-.id
。
使用临时变量
nebula> $var = GO FROM "player100" OVER follow YIELD follow._dst AS id; \
GO FROM $var.id OVER serve YIELD $$.team.name AS Team, \
$^.player.name AS Player;
+---------+-------------+
| Team | Player |
+---------+-------------+
| Nuggets | Tony Parker |
+---------+-------------+
Got 1 rows (time spent 3103/3711 us)
当复合语句作为一个整体提交给服务器时,其中的临时变量会在语句结束时被释放。
9.7.2 FETCH语句示例
查询VID为player100的球员的属性
nebula> FETCH PROP ON player "player100";
+----------------------------------------------------+
| vertices_ |
+----------------------------------------------------+
| ("player100" :player{age: 42, name: "Tim Duncan"}) |
+----------------------------------------------------+
Got 1 rows (time spent 2006/2406 us)
9.8 修改点和边
用户可以使用UPDATE语句或UPSERT语句修改现有数据。UPSERT是UPDATE和INSERT的结合体。当使用UPSERT更新一个点或边,如果它不存在,数据库会自动插入一个新的点或边。
UPSERT操作是基于Nebula Graph的分区进行串行操作,所以执行速度比单独执行INSERT或UPDATE慢。
9.8.1 nGQL语法
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>];
9.8.2 示例
用UPDATE修改VID为player100的球员的name属性
nebula> UPDATE VERTEX "player100" SET player.name = "Tim";
用UPDATE修改某条边的degree属性
nebula> UPDATE EDGE "player100" -> "player101" OF follow SET degree = 96;
用UPSERT插入一个VID为player111的点
nebula> UPSERT VERTEX "player111" SET player.name = "Dwight Howard", player.age = $^.player.age + 11 \
WHEN $^.player.name == "Ben Simmons" AND $^.player.age > 20 \
YIELD $^.player.name AS Name, $^.player.age AS Age;
9.9 删除点和边
9.9.1 nGQL语法
删除点
DELETE VERTEX <vid1>[, <vid2>...]
删除边
DELETE EDGE <edge_type> <src_vid> -> <dst_vid>[@<rank>]
[, <src_vid> -> <dst_vid>...]
9.9.2 示例
删除点
nebula> DELETE VERTEX "team1", "team2";
删除边
nebula> DELETE EDGE follow "team1" -> "team2";
9.10 索引
用户可以通过CREATE INDEX语句为标签(tag)和边类型(edge type)增加索引。
9.10.1 使用索引注意事项
MATCH和LOOKUP语句的执行都依赖索引,但是索引会导致写性能大幅降低(降低90%甚至更多)。请不要随意在生产环境中使用索引,除非很清楚使用索引对业务的影响。
必须为已存在的数据重建索引,否则不能索引已存在的数据,导致无法在MATCH和LOOKUP语句中返回这些数据。
9.10.2 nGQL语法
创建索引
CREATE {TAG | EDGE} INDEX [IF NOT EXISTS] <index_name>
ON {<tag_name> | <edge_name>} (prop_name_list);
重建索引
REBUILD {TAG | EDGE} INDEX <index_name>;
9.10.3 示例
为标签player的属性name创建索引,并且重建索引。
nebula> CREATE TAG INDEX player_index_0 on player(name(20));
nebula> REBUILD TAG INDEX player_index_0;
为没有指定长度的变量属性创建索引时,需要指定索引长度。在utf-8编码中,一个中文字符占3字节,需要根据变量属性长度设置合适的索引长度。例如10个中文字符,索引长度需要为30。
9.10.4 基于索引的LOOKUP和MATCH示例
确保LOOKUP或MATCH有一个索引可用。如果没有,请先创建索引。找到标签为player的点的信息,它的name属性值为Tony Parker。
使用LOOKUP语句检索点的属性
nebula> LOOKUP ON player WHERE player.name == "Tony Parker" \
YIELD player.name, player.age;
使用MATCH语句检索点的属性。
nebula> MATCH (v:player{name:"Tony Parker"}) RETURN v;
十、复合查询(子句结构)
复合查询将来自不同请求的数据放在一起,然后进行过滤、分组或者排序等,最后返回结果。Nebula Graph支持三种方式进行复合查询(或子查询)
- (OpenCypher语句)连接各个子句,让它们在彼此之间提供中间结果集。
- (nGQL扩展)多个查询可以合并处理,以英文分号(;)分隔,返回最后一个查询的结果。
- (nGQL扩展)可以用管道符(|)将多个查询连接起来,上一个查询的结果可以作为下一个查询的输入。
10.1 OpenCypher语句
MATCH、RETURN、WITH等
10.2 nGQL扩展语句
FETCH、GO、LOOKUP等
10.3 OpenCypher兼容性
在复合查询中,请不要混用OpenCypher语句和nGQL扩展语句,例如MATCH ... | GO ... | YIELD ...,混用两种语句,行为是未定义的。
如果使用OpenCypher语句(MATCH、RETURN、WITH等),请不要使用管道符或分号组合子句。
如果使用nGQL扩展语句(FETCH、GO、LOOKUP等),必须使用管道符或分号组合子句。
十一、自定义变量
Nebula Graph允许将一条语句的结果作为自定义变量传递给另一条语句。
11.1 OpenCypher兼容性
当引用一个变量的点、边或路径,需要先给它命名。例如:
nebula> MATCH (v:player{name:"Tim Duncan"}) RETURN v;
示例中的v就是自定义变量。
11.2 nGQL扩展
nGQL扩展的自定义变量可以表示为$<var_name>,var_name由字母、数字或下划线(_)构成,不允许使用其他字符。
自定义变量仅在当前执行有效,执行结束后变量也会释放,不能在其他客户端或执行中使用之前的自定义变量。
nebula> $var = GO FROM "player100" OVER follow YIELD follow._dst AS id; \
GO FROM $var.id OVER serve YIELD $$.team.name AS Team, \
$^.player.name AS Player;
+---------+-------------+
| Team | Player |
+---------+-------------+
| Nuggets | Tony Parker |
+---------+-------------+
十二、引用属性
用户可以在WHERE和YIELD子句中引用点或边的属性。
12.1 引用点的属性
起始点
$^.<tag_name>.<prop_name>
目的点
$$.tag_name.prop_name
12.2 引用边的属性
引用自定义的边属性
<edge_type>.<prop_name>
引用内置的边属性
除了自定义的边属性,每条边还有如下三种内置属性:
12.3 示例
# 返回起始点的标签player的name属性值和目的点的标签player的age属性值。
nebula> GO FROM "player100" OVER follow YIELD $^.player.name AS startName, $$.player.age AS endAge;
+--------------+--------+
| startName | endAge |
+--------------+--------+
| "Tim Duncan" | 36 |
+--------------+--------+
| "Tim Duncan" | 33 |
+--------------+--------+
# 返回边类型follow的degree属性值。
nebula> GO FROM "player100" OVER follow YIELD follow.degree;
+---------------+
| follow.degree |
+---------------+
| 95 |
+---------------+
| 90 |
+---------------+
# 返回边类型follow的起始点、目的点、边类型编码和边rank值。
nebula> GO FROM "player100" OVER follow YIELD follow._src, follow._dst, follow._type, follow._rank;
+-------------+-------------+--------------+--------------+
| follow._src | follow._dst | follow._type | follow._rank |
+-------------+-------------+--------------+--------------+
| "player100" | "player101" | 136 | 0 |
+-------------+-------------+--------------+--------------+
| "player100" | "player102" | 136 | 0 |
+-------------+-------------+--------------+--------------+
十三、运算符
13.1 集合运算符
合并多个请求时,可以使用集合运算符,包括UNION、UNION ALL、INTERSECT和MINUS。所有集合运算符的优先级相同,如果一个nGQL语句中有多个集合运算符,Nebula Graph会从左到右进行计算,除非用括号指定顺序。
运算符UNION DISTINCT(或使用缩写UNION)返回两个集合A和B的并集,不包含重复的元素。
运算符UNION ALL返回两个集合A和B的并集,包含重复的元素。
left和right必须有相同数量的列和数据类型。
13.1.1 UNION DISTINCT
返回两个查询结果的并集,不包含重复的元素(有重复数据去重,只留一个)
nebula> GO FROM "player102" OVER follow \
UNION \
GO FROM "player100" OVER follow;
+-------------+
| follow._dst |
+-------------+
| "player101" |
+-------------+
| "player102" |
+-------------+
13.1.2 UNION ALL
返回两个查询结果的并集,包含重复的元素
nebula> GO FROM "player102" OVER follow \
UNION ALL \
GO FROM "player100" OVER follow;
+-------------+
| follow._dst |
+-------------+
| "player101" |
+-------------+
| "player101" |
+-------------+
| "player102" |
+-------------+
UNION也可以和YIELD语句一起使用,去重时会检查每一行的所有列,每列都相同时才会去重
nebula> GO FROM "player102" OVER follow \
YIELD follow._dst AS id, follow.degree AS Degree, $$.player.age AS Age \
UNION /* DISTINCT */ \
GO FROM "player100" OVER follow \
YIELD follow._dst AS id, follow.degree AS Degree, $$.player.age AS Age;
+-------------+--------+-----+
| id | Degree | Age |
+-------------+--------+-----+
| "player101" | 75 | 36 |
+-------------+--------+-----+
| "player101" | 96 | 36 |
+-------------+--------+-----+
| "player102" | 90 | 33 |
+-------------+--------+-----+
13.1.3 INTERSECT
运算符INTERSECT返回两个集合A和B的交集
nebula> GO FROM "player102" OVER follow \
YIELD follow._dst AS id, follow.degree AS Degree, $$.player.age AS Age \
INTERSECT \
GO FROM "player100" OVER follow \
YIELD follow._dst AS id, follow.degree AS Degree, $$.player.age AS Age;
13.1.4 MINUS
运算符MINUS返回两个集合A和B的差异,即A-B。请注意left和right的顺序,A-B表示在集合A中,但是不在集合B中的元素。
nebula> GO FROM "player100" OVER follow \
MINUS \
GO FROM "player102" OVER follow;
+-------------+
| follow._dst |
+-------------+
| "player102" |
+-------------+
13.1.5 集合运算符和管道符的优先级
当查询包含集合运算符和管道符(|)时,管道符的优先级高。例如GO FROM 1 UNION GO FROM 2 | GO FROM 3
相当于GO FROM 1 UNION (GO FROM 2 | GO FROM 3)
。
13.2 字符串运算符
Nebula Graph支持使用字符串运算符进行连接、搜索、匹配运算。支持的运算符如下
十四、函数和表达式
14.1 CASE表达式
CASE表达式使用条件来过滤nGQL查询语句的结果,常用于YIELD和RETURN子句中。和openCypher一样,nGQL提供两种形式的CASE表达式:简单形式和通用形式。
CASE表达式会遍历所有条件,并在满足第一个条件时停止读取后续条件,然后返回结果。如果不满足任何条件,将通过ELSE子句返回结果。如果没有ELSE子句且不满足任何条件,则返回NULL。
nebula> GO FROM "player100" OVER follow \
YIELD $$.player.name AS Name, \
CASE $$.player.age > 35 \
WHEN true THEN "Yes" \
WHEN false THEN "No" \
ELSE "Nah" \
END \
AS Age_above_35;
+---------------------+--------------+
| Name | Age_above_35 |
+---------------------+--------------+
| "Tony Parker" | "Yes" |
+---------------------+--------------+
| "LaMarcus Aldridge" | "No" |
+---------------------+--------------+
14.2 count函数
count()函数可以计数指定的值或行数。
(nGQL扩展)用户可以同时使用count()和GROUP BY对指定的值进行分组和计数,再使用YIELD返回结果。
(openCypher方式)用户可以使用count()对指定的值进行计数,再使用RETURN返回结果。不需要使用GROUP BY。
# 返回player101 follow的人,以及follow player101的人,即双向查询。
nebula> GO FROM "player101" OVER follow BIDIRECT \
YIELD $$.player.name AS Name \
| GROUP BY $-.Name YIELD $-.Name, count(*);
+---------------------+----------+
| $-.Name | COUNT(*) |
+---------------------+----------+
| "Dejounte Murray" | 1 |
+---------------------+----------+
| "LaMarcus Aldridge" | 2 |
+---------------------+----------+
| "Tim Duncan" | 2 |
+---------------------+----------+
| "Marco Belinelli" | 1 |
+---------------------+----------+
| "Manu Ginobili" | 1 |
+---------------------+----------+
| "Boris Diaw" | 1 |
+---------------------+----------+
补充:REVERSELY、BIDIRECT
//查询273关注的人 (正向查询)
GO FROM '273' OVER focusEdge;
//查询关注273的人 (反向查询)
GO FROM '273' OVER focusEdge REVERSELY;
//查询273关注的人 & 关注273的人 (双向查询)
GO FROM '273' OVER focusEdge BIDIRECT;
14.3 collect函数
collect()函数返回一个符合表达式返回结果的列表。该函数可以将多条记录或值合并进一个列表,实现数据聚合。collect()是一个聚合函数,类似SQL中的GROUP BY
# 基于年龄聚合姓名。
nebula> MATCH (n:player) \
RETURN n.age AS age, collect(n.name);
+-----+--------------------------------------------------------------------------+
| age | collect(n.name) |
+-----+--------------------------------------------------------------------------+
| 24 | ["Giannis Antetokounmpo"] |
+-----+--------------------------------------------------------------------------+
| 20 | ["Luka Doncic"] |
+-----+--------------------------------------------------------------------------+
| 25 | ["Joel Embiid", "Kyle Anderson"] |
+-----+--------------------------------------------------------------------------+
14.4 hash函数
hash()函数返回参数的哈希值。其参数可以是数字、字符串、列表、布尔值、NULL等类型的值,或者计算结果为这些类型的表达式。
nGQL 1.0不支持字符串类型的VID,一种常用的处理方式是用hash函数获取字符串的哈希值,然后将该值设置为VID。但nGQL 2.0同时支持了字符串和整数类型的VID,所以无需再使用这种方式设置VID。
在Java中的调用方式如下
MurmurHash2.hash64("to_be_hashed".getBytes(),"to_be_hashed".getBytes().length, 0xc70f6907)
十五、通用查询语句
15.1 MATCH(依赖索引)
MATCH语句提供基于模式(pattern)匹配的搜索功能。一个MATCH语句定义了一个搜索模式,用该模式匹配存储在Nebula Graph中的数据,然后用RETURN子句检索数据。
MATCH语句使用原生索引查找起始点,起始点可以在模式的任何位置。即一个有效的MATCH语句,必须有一个属性、标签或者点已经创建索引。
nGQL不支持遍历所有点和边,例如MATCH (v) RETURN v。但是,建立相应Tag的索引后,可以遍历对应Tag的所有点,例如MATCH (v:T1) RETURN v。
15.1.2 匹配点 & 匹配标签
用户可以在一对括号中使用自定义变量来表示模式中的点,例如(v)。用户可以在点的右侧用:<tag_name>表示模式中的标签。
nebula> MATCH (v:player) RETURN v;
+---------------------------------------------------------------+
| v |
+---------------------------------------------------------------+
| ("player102" :player{age: 33, name: "LaMarcus Aldridge"}) |
+---------------------------------------------------------------+
| ("player106" :player{age: 25, name: "Kyle Anderson"}) |
+---------------------------------------------------------------+
| ("player115" :player{age: 40, name: "Kobe Bryant"}) |
+---------------------------------------------------------------+
15.1.3 匹配点的属性
用户可以在标签的右侧用{<prop_name>: <prop_value>}表示模式中点的属性
# 使用属性name搜索匹配的点。
nebula> MATCH (v:player{name:"Tim Duncan"}) RETURN v;
+----------------------------------------------------+
| v |
+----------------------------------------------------+
| ("player100" :player{name: "Tim Duncan", age: 42}) |
+----------------------------------------------------+
使用WHERE子句也可以实现相同的操作
nebula> MATCH (v:player) WHERE v.name == "Tim Duncan" RETURN v;
+----------------------------------------------------+
| v |
+----------------------------------------------------+
| ("player100" :player{name: "Tim Duncan", age: 42}) |
+----------------------------------------------------+
15.1.4 匹配点ID
用户可以使用点ID去匹配点。id()函数可以检索点的ID
nebula> MATCH (v) WHERE id(v) == 'player101' RETURN v;
+---------------------------------------------------+
| v |
+---------------------------------------------------+
| (player101) player.name:Tony Parker,player.age:36 |
+---------------------------------------------------+
要匹配多个点的ID,可以用WHERE id(v) IN [vid_list]
15.1.5 匹配连接的点
用户可以使用--符号表示两个方向的边,并匹配这些边连接的点。(在nGQL 1.x中,--符号用于行内注释,在nGQL 2.x中,--符号表示出边或入边)
nebula> MATCH (v:player{name:"Tim Duncan"})--(v2) \
RETURN v2.name AS Name;
+---------------------+
| Name |
+---------------------+
| "Tony Parker" |
+---------------------+
用户可以在--符号上增加<或>符号指定边的方向
# -->表示边从v开始,指向v2。对于点v来说是出边,对于点v2来说是入边。
nebula> MATCH (v:player{name:"Tim Duncan"})-->(v2) \
RETURN v2.name AS Name;
+-----------------+
| Name |
+-----------------+
| "Spurs" |
+-----------------+
| "Tony Parker" |
15.1.6 匹配路径
连接起来的点和边构成了路径。用户可以使用自定义变量命名路径
nebula> MATCH p=(v:player{name:"Tim Duncan"})-->(v2) \
RETURN p;
+-------------------------------------------+
| p |
+-------------------------------------------+
| <("player100" :player{age: 42, name: "Tim Duncan"})-[:follow@0 {degree: 95}]->("player101" :player{age: 36, name: "Tony Parker"})>
15.1.7 匹配边
除了用--、-->、<--表示未命名的边之外,用户还可以在方括号中使用自定义变量命名边。例如-[e]-
nebula> MATCH (v:player{name:"Tim Duncan"})-[e]-(v2) \
RETURN e;
+---------------------------------------------------------------------------+
| e |
+---------------------------------------------------------------------------+
| [:follow "player101"->"player100" @0 {degree: 95}]
15.1.8 匹配边类型和属性
和点一样,用户可以用:<edge_type>表示模式中的边类型。例如-[e:serve]-
nebula> MATCH (v:player{name:"Tim Duncan"})-[e:serve]-(v2) \
RETURN e;
+---------------------------------------------------------------------------+
| e |
+---------------------------------------------------------------------------+
| [:serve "player100"->"team204" @0 {end_year: 2016, start_year: 1997}] |
+---------------------------------------------------------------------------+
15.1.9 匹配多个边类型
使用|可以匹配多个边类型。例如[e:follow|:serve]
nebula> MATCH (v:player{name:"Tim Duncan"})-[e:follow|:serve]->(v2) \
RETURN e;
+---------------------------------------------------------------------------+
| e |
+---------------------------------------------------------------------------+
| [:follow "player100"->"player101" @0 {degree: 95}] |
+---------------------------------------------------------------------------+
| [:follow "player100"->"player125" @0 {degree: 95}]
15.2 LOOKUP(依赖索引)
15.2.1 前提条件
请确保LOOKUP语句有至少一个索引可用。如果需要创建索引,但是已经有相关的点、边或属性,用户必须在创建索引后重建索引,索引才能生效。
15.2.2 检索点
返回标签为player且name为Tony Parker的点
nebula> LOOKUP ON player WHERE player.name == "Tony Parker" \
YIELD player.name, player.age;
=======================================
| VertexID | player.name | player.age |
=======================================
| 101 | Tony Parker | 36 |
15.2.3 检索边
返回边类型为follow且degree为90的边
nebula> LOOKUP ON follow WHERE follow.degree == 90 YIELD follow.degree;
=============================================
| SrcVID | DstVID | Ranking | follow.degree |
=============================================
| 100 | 106 | 0 | 90 |
15.2.4 通过标签列出所有的对应的点
如果需要通过标签列出所有的点,或通过边类型列出边,则标签、边类型或属性上必须有至少一个索引。
nebula> LOOKUP ON player;
+-------------+
| _vid |
+-------------+
| "player100" |
+-------------+
| "player101" |
+-------------+
15.2.5 通过边类型列出边
nebula)> LOOKUP ON like;
+-------------+----------+-------------+
| _src | _ranking | _dst |
+-------------+----------+-------------+
| "player100" | 0 | "player101" |
+-------------+----------+-------------+
15.2.6 统计点或边
统计点(依赖索引)
nebula> LOOKUP ON player | YIELD COUNT(*) AS Player_Number;
+---------------+
| Player_Number |
+---------------+
| 2 |
+---------------+
统计边(依赖索引)
nebula> LOOKUP ON like | YIELD COUNT(*) AS Like_Number;
+-------------+
| Like_Number |
+-------------+
| 1 |
+-------------+
15.3 GO
15.3.1 语法
GO [[<M> TO] <N> STEPS ] FROM <vertex_list>
OVER <edge_type_list> [{REVERSELY | BIDIRECT}]
[ WHERE <conditions> ]
[YIELD [DISTINCT] <return_list>]
[| ORDER BY <expression> [{ASC | DESC}]]
[| LIMIT [<offset_value>,] <number_rows>]
GO [[<M> TO] <N> STEPS ] FROM <vertex_list>
OVER <edge_type_list> [{REVERSELY | BIDIRECT}]
[ WHERE <conditions> ]
[| GROUP BY {col_name | expr | position} YIELD <col_name>]
<vertex_list> ::=
<vid> [, <vid> ...]
<edge_type_list> ::=
edge_type [, edge_type ...]
| *
<return_list> ::=
<col_name> [AS <col_alias>] [, <col_name> [AS <col_alias>] ...]
<N> STEPS
:指定跳数。如果没有指定跳数,默认值N
为1
。如果N
为0
,Nebula Graph不会检索任何边。M TO N STEPS
:遍历M~N
跳的边。如果M
为0
,输出结果和M
为1
相同,即GO 0 TO 2
和GO 1 TO 2
是相同的。<vertex_list>
:用逗号分隔的点ID列表,或特殊的引用符$-.id
。<edge_type_list>
:遍历的边类型列表。REVERSELY | BIDIRECT
:默认情况下检索的是<vertex_list>
的出边,REVERSELY
表示反向,即检索入边,BIDIRECT
表示双向,即检索出边和入边。WHERE <conditions>
:指定遍历的过滤条件。用户可以在起始点、目的点和边使用WHERE
子句,还可以结合AND
、OR
、NOT
、XOR
一起使用。YIELD [DISTINCT] <return_list>
:指定输出结果。如果没有指定,默认返回目的点ID。ORDER BY
:指定输出结果的排序规则。LIMIT
:限制输出结果的行数。GROUP BY
:根据指定属性的值将输出分组。
15.3.2 示例
遍历边
# 返回player102所属队伍。
nebula> GO FROM "player102" OVER serve;
+------------+
| serve._dst |
+------------+
| "team203" |
+------------+
| "team204" |
+------------+
按跳数查询
// 查询1跳:返回结果273 (数据关系:54关注273,273关注102、300)
GO 1 STEPS FROM "54" OVER focusEdge;
// 查询2跳:返回结果102,300(数据关系:54关注273,273关注102、300)
GO 2 STEPS FROM "54" OVER focusEdge;
遍历多个边类型
# 遍历多个边类型。属性没有值时,会显示__EMPTY__。
nebula> GO FROM "player100" OVER follow, serve \
YIELD follow.degree, serve.start_year;
+---------------+------------------+
| follow.degree | serve.start_year |
+---------------+------------------+
| 95 | __EMPTY__ |
+---------------+------------------+
| 95 | __EMPTY__ |
+---------------+------------------+
| __EMPTY__ | 1997 |
+---------------+------------------+
// 查询273关注的又是好友的人
GO FROM "273" OVER focusEdge, friendsEdge
返回入边
# 返回player100的入边。
nebula> GO FROM "player100" OVER follow REVERSELY \
YIELD follow._dst AS destination;
+-------------+
| destination |
+-------------+
| "player101" |
+-------------+
| "player102" |
+-------------+
返回出边和入边
# 返回player102的出边和入边。
nebula> GO FROM "player102" OVER follow BIDIRECT \
YIELD follow._dst AS both;
+-------------+
| both |
+-------------+
| "player100" |
+-------------+
| "player101" |
+-------------+
查询player100的朋友和朋友所属队伍
nebula> GO FROM "player100" 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;
+---------------------+-----------------+
| FriendOf | Team |
+---------------------+-----------------+
| "Tony Parker" | "Spurs" |
+---------------------+-----------------+
| "Tony Parker" | "Hornets" |
+---------------------+-----------------+
分组并限制输出结果的行数
# 分组并限制输出结果的行数。
nebula> $a = GO FROM "player100" OVER follow YIELD follow._src AS src, follow._dst AS dst; \
GO 2 STEPS FROM $a.dst OVER follow \
YIELD $a.src AS src, $a.dst, follow._src, follow._dst \
| ORDER BY $-.src | OFFSET 1 LIMIT 2;
+-------------+-------------+-------------+-------------+
| src | $a.dst | follow._src | follow._dst |
+-------------+-------------+-------------+-------------+
| "player100" | "player125" | "player100" | "player101" |
+-------------+-------------+-------------+-------------+
| "player100" | "player101" | "player100" | "player125" |
+-------------+-------------+-------------+-------------+
15.4 FETCH
15.4.1 获取点的属性值
语法
FETCH PROP ON {<tag_name>[, tag_name ...] | *}
<vid> [, vid ...]
[YIELD <output>]
基于标签获取点的属性值
nebula> FETCH PROP ON player "player100";
+----------------------------------------------------+
| vertices_ |
+----------------------------------------------------+
| ("player100" :player{age: 42, name: "Tim Duncan"}) |
+----------------------------------------------------+
获取点的指定属性值
nebula> FETCH PROP ON player "player100" \
YIELD player.name;
+-------------+--------------+
| VertexID | player.name |
+-------------+--------------+
| "player100" | "Tim Duncan" |
+-------------+--------------+
获取多个点的属性值
nebula> FETCH PROP ON player "player101", "player102", "player103";
+-----------------------------------------------------------+
| vertices_ |
+-----------------------------------------------------------+
| ("player101" :player{age: 36, name: "Tony Parker"}) |
+-----------------------------------------------------------+
| ("player102" :player{age: 33, name: "LaMarcus Aldridge"}) |
+-----------------------------------------------------------+
| ("player103" :player{age: 32, name: "Rudy Gay"}) |
+-----------------------------------------------------------+
基于多个标签获取点的属性值
# 基于标签player和t1获取点player100上的属性值。
nebula> FETCH PROP ON player, t1 "player100";
+----------------------------------------------------------------------------+
| vertices_ |
+----------------------------------------------------------------------------+
| ("player100" :t1{a: "Hello", b: 100} :player{age: 42, name: "Tim Duncan"}) |
+----------------------------------------------------------------------------+
15.4.2 获取边的属性值
语法
FETCH PROP ON <edge_type> <src_vid> -> <dst_vid>[@<rank>] [, <src_vid> -> <dst_vid> ...]
[YIELD <output>]
获取边的所有属性值
# 获取连接player100和team204的边serve的所有属性值。
nebula> FETCH PROP ON serve "player100" -> "team204";
+-----------------------------------------------------------------------+
| edges_ |
+-----------------------------------------------------------------------+
| [:serve "player100"->"team204" @0 {end_year: 2016, start_year: 1997}] |
+-----------------------------------------------------------------------+
获取边的指定属性值
nebula> FETCH PROP ON serve "player100" -> "team204" \
YIELD serve.start_year;
+-------------+------------+-------------+------------------+
| serve._src | serve._dst | serve._rank | serve.start_year |
+-------------+------------+-------------+------------------+
| "player100" | "team204" | 0 | 1997 |
+-------------+------------+-------------+------------------+
获取多条边的属性值
nebula> FETCH PROP ON serve "player100" -> "team204", "player133" -> "team202";
+-----------------------------------------------------------------------+
| edges_ |
+-----------------------------------------------------------------------+
| [:serve "player100"->"team204" @0 {end_year: 2016, start_year: 1997}] |
+-----------------------------------------------------------------------+
| [:serve "player133"->"team202" @0 {end_year: 2011, start_year: 2002}] |
+-----------------------------------------------------------------------+
基于rank获取属性值
如果有多条边,起始点、目的点和边类型都相同,可以通过指定rank获取正确的边属性值
# 插入不同属性值、不同rank的边。
nebula> insert edge serve(start_year,end_year) \
values "player100"->"team204"@1:(1998, 2017);
nebula> insert edge serve(start_year,end_year) \
values "player100"->"team204"@2:(1990, 2018);
# 默认返回rank为0的边。
nebula> FETCH PROP ON serve "player100" -> "team204";
+-----------------------------------------------------------------------+
| edges_ |
+-----------------------------------------------------------------------+
| [:serve "player100"->"team204" @0 {end_year: 2016, start_year: 1997}] |
+-----------------------------------------------------------------------+
# 要获取rank不为0的边,请在FETCH语句中设置rank。
nebula> FETCH PROP ON serve "player100" -> "team204"@1;
+-----------------------------------------------------------------------+
| edges_ |
+-----------------------------------------------------------------------+
| [:serve "player100"->"team204" @1 {end_year: 2017, start_year: 1998}] |
+-----------------------------------------------------------------------+
复合语句中使用FETCH
将FETCH与nGQL扩展结合使用是一种常见的方式,例如和GO一起
# 返回从点player101开始的follow边的degree值。
nebula> GO FROM "player101" OVER follow \
YIELD follow._src AS s, follow._dst AS d \
| FETCH PROP ON follow $-.s -> $-.d \
YIELD follow.degree;
+-------------+-------------+--------------+---------------+
| follow._src | follow._dst | follow._rank | follow.degree |
+-------------+-------------+--------------+---------------+
| "player101" | "player100" | 0 | 95 |
+-------------+-------------+--------------+---------------+
| "player101" | "player102" | 0 | 90 |
+-------------+-------------+--------------+---------------+
| "player101" | "player125" | 0 | 95 |
+-------------+-------------+--------------+---------------+
15.5 UNWIND
UNWIND语句可以将列表拆分为单独的行,列表中的每个元素为一行。UNWIND可以作为单独语句或语句中的子句使用。
nebula> MATCH p=(v:player{name:"Tim Duncan"})--(v2) \
WITH nodes(p) AS n \
UNWIND n AS r \
WITH DISTINCT r AS r \
RETURN collect(r);
+----------------------------------------------------------------------------------------------------------------------+
| COLLECT(r) |
+----------------------------------------------------------------------------------------------------------------------+
| [("player100" :player{age: 42, name: "Tim Duncan"}), ("player101" :player{age: 36, name: "Tony Parker"}),
("team204" :team{name: "Spurs"}), ("player102" :player{age: 33, name: "LaMarcus Aldridge"}),
("player125" :player{age: 41, name: "Manu Ginobili"}), ("player104" :player{age: 32, name: "Marco Belinelli"}),
("player144" :player{age: 47, name: "Shaquile O'Neal"}), ("player105" :player{age: 31, name: "Danny Green"}),
("player113" :player{age: 29, name: "Dejounte Murray"}), ("player107" :player{age: 32, name: "Aron Baynes"}),
("player109" :player{age: 34, name: "Tiago Splitter"}), ("player108" :player{age: 36, name: "Boris Diaw"})] |
+----------------------------------------------------------------------------------------------------------------------+
15.6 SHOW
15.6.1 SHOW CHARSET
显示当前的字符集
nebula> SHOW CHARSET;
+---------+-----------------+-------------------+--------+
| Charset | Description | Default collation | Maxlen |
+---------+-----------------+-------------------+--------+
| "utf8" | "UTF-8 Unicode" | "utf8_bin" | 4 |
+---------+-----------------+-------------------+--------+
15.6.2 SHOW COLLATION
显示当前的排序规则
nebula> SHOW COLLATION;
+------------+---------+
| Collation | Charset |
+------------+---------+
| "utf8_bin" | "utf8" |
+------------+---------+
15.6.3 SHOW CREATE SPACE
显示指定图空间的基本信息,例如创建图空间的nGQL、分片数量、副本数量等。
nebula> SHOW CREATE SPACE basketballplayer;
+--------------------+---------------------------------------------------------------------------------------------------------------------------------------------+
| Space | Create Space |
+--------------------+---------------------------------------------------------------------------------------------------------------------------------------------+
| "basketballplayer" | "CREATE SPACE `basketballplayer` (partition_num = 10, replica_factor = 1, charset = utf8, collate = utf8_bin, vid_type = FIXED_STRING(32))" |
+--------------------+---------------------------------------------------------------------------------------------------------------------------------------------+
15.6.4 SHOW CREATE TAG/EDGE
显示指定标签的基本信息/显示指定边类型的基本信息
nebula> SHOW CREATE TAG player;
+----------+-----------------------------------+
| Tag | Create Tag |
+----------+-----------------------------------+
| "player" | "CREATE TAG `player` ( |
| | `name` string NULL, |
| | `age` int64 NULL |
| | ) ttl_duration = 0, ttl_col = "" |
+----------+-----------------------------------+
nebula> SHOW CREATE EDGE follow;
+----------+-----------------------------------+
| Edge | Create Edge |
+----------+-----------------------------------+
| "follow" | "CREATE EDGE `follow` ( |
| | `degree` int64 NULL |
| | ) ttl_duration = 0, ttl_col = """ |
+----------+-----------------------------------+
15.6.5 SHOW HOSTS
显示由Meta服务注册的Graph、Storage、Meta主机
nebula> SHOW HOSTS;
+-------------+-------+----------+--------------+----------------------------------+-----------------------------+
| Host | Port | Status | Leader count | Leader distribution | Partition distribution |
+-------------+-------+----------+--------------+----------------------------------+-----------------------------+
| "storaged0" | 9779 | "ONLINE" | 8 | "docs:5, basketballplayer:3" | "docs:5, basketballplayer:3"|
+-------------+-------+----------+--------------+----------------------------------+-----------------------------+
| "storaged1" | 9779 | "ONLINE" | 9 | "basketballplayer:4, docs:5" | "docs:5, basketballplayer:4"|
+-------------+-------+----------+--------------+----------------------------------+-----------------------------+
| "storaged2" | 9779 | "ONLINE" | 8 | "basketballplayer:3, docs:5" | "docs:5, basketballplayer:3"|
+-------------+-------+----------+--------------+----------------------------------+-----------------------------+
Got 3 rows (time spent 866/1411 us)
nebula> SHOW HOSTS GRAPH;
+-------------+------+----------+---------+--------------+
| Host | Port | Status | Role | Git Info Sha |
+-------------+------+----------+---------+--------------+
| "12.16.2.3" | 9669 | "ONLINE" | "GRAPH" | "761f22b" |
nebula> SHOW HOSTS STORAGE;
+-------------+------+----------+-----------+--------------+
| Host | Port | Status | Role | Git Info Sha |
+-------------+------+----------+-----------+--------------+
| "12.16.2.3" | 9779 | "ONLINE" | "STORAGE" | "761f22b" |
nebula> SHOW HOSTS META;
+-------------+------+----------+--------+--------------+
| Host | Port | Status | Role | Git Info Sha |
+-------------+------+----------+--------+--------------+
| "12.16.2.3" | 9559 | "ONLINE" | "META" | "761f22b" |
15.6.6 SHOW INDEX STATUS
显示重建原生索引的作业状态,以便确定重建索引是否成功
nebula> SHOW TAG INDEX STATUS;
+----------------+--------------+
| Name | Index Status |
+----------------+--------------+
| "like_index_0" | "FINISHED" |
+----------------+--------------+
| "like1" | "FINISHED" |
+----------------+--------------+
nebula> SHOW EDGE INDEX STATUS;
+----------------+--------------+
| Name | Index Status |
+----------------+--------------+
| "index_follow" | "FINISHED" |
+----------------+--------------+
15.6.7 SHOW INDEXES
显示现有的原生索引
nebula> SHOW TAG INDEXES;
+------------------+
| Names |
+------------------+
| "play_age_0" |
+------------------+
| "player_index_0" |
+------------------+
nebula> SHOW EDGE INDEXES;
+----------------+
| Names |
+----------------+
| "index_follow" |
+----------------+
15.6.8 SHOW PARTS
显示图空间指定分片或所有分片的信息
nebula> SHOW PARTS;
+--------------+-------------------+-------------------+-------+
| Partition ID | Leader | Peers | Losts |
+--------------+-------------------+-------------------+-------+
| 1 | "storaged1:44500" | "storaged1:44500" | "" |
+--------------+-------------------+-------------------+-------+
| 2 | "storaged2:44500" | "storaged2:44500" | "" |
+--------------+-------------------+-------------------+-------+
| 3 | "storaged0:44500" | "storaged0:44500" | "" |
+--------------+-------------------+-------------------+-------+
nebula> SHOW PARTS 1;
+--------------+-------------------+-------------------+-------+
| Partition ID | Leader | Peers | Losts |
+--------------+-------------------+-------------------+-------+
| 1 | "storaged1:44500" | "storaged1:44500" | "" |
+--------------+-------------------+-------------------+-------+
15.6.9 SHOW ROLES
显示分配给用户的角色信息
nebula> SHOW ROLES in basketballplayer;
+---------+-----------+
| Account | Role Type |
+---------+-----------+
| "user1" | "ADMIN" |
+---------+-----------+
15.6.10 SHOW SNAPSHOTS
显示所有快照信息
nebula> SHOW SNAPSHOTS;
+--------------------------------+---------+-----------------------------------------------------+
| Name | Status | Hosts |
+--------------------------------+---------+-----------------------------------------------------+
| "SNAPSHOT_2020_12_16_11_13_55" | "VALID" | "storaged0:9779, storaged1:9779, storaged2:9779" |
+--------------------------------+---------+-----------------------------------------------------+
| "SNAPSHOT_2020_12_16_11_14_10" | "VALID" | "storaged0:9779, storaged1:9779, storaged2:9779" |
+--------------------------------+---------+-----------------------------------------------------+
15.6.11 SHOW SPACES
显示现存的图空间
nebula> SHOW SPACES;
+---------------------+
| Name |
+---------------------+
| "docs" |
+---------------------+
| "basketballplayer" |
+---------------------+
15.6.12 SHOW STATS
显示最近STATS作业收集的图空间统计信息,在需要查看统计信息的图空间中执行SUBMIT JOB STATS
# 选择图空间。
nebula> USE basketballplayer;
# 执行SUBMIT JOB STATS。
nebula> SUBMIT JOB STATS;
+------------+
| New Job Id |
+------------+
| 98 |
+------------+
# 确认作业执行成功。
nebula> SHOW JOB 98;
+----------------+---------------+------------+------------+------------+
| Job Id(TaskId) | Command(Dest) | Status | Start Time | Stop Time |
+----------------+---------------+------------+------------+------------+
| 98 | "STATS" | "FINISHED" | 1606552675 | 1606552675 |
+----------------+---------------+------------+------------+------------+
| 0 | "storaged2" | "FINISHED" | 1606552675 | 1606552675 |
+----------------+---------------+------------+------------+------------+
| 1 | "storaged0" | "FINISHED" | 1606552675 | 1606552675 |
+----------------+---------------+------------+------------+------------+
| 2 | "storaged1" | "FINISHED" | 1606552675 | 1606552675 |
+----------------+---------------+------------+------------+------------+
# 显示图空间统计信息。
nebula> SHOW STATS;
+---------+------------+-------+
| Type | Name | Count |
+---------+------------+-------+
| "Tag" | "player" | 51 |
+---------+------------+-------+
| "Tag" | "team" | 30 |
+---------+------------+-------+
| "Edge" | "like" | 81 |
+---------+------------+-------+
| "Edge" | "serve" | 152 |
+---------+------------+-------+
| "Space" | "vertices" | 81 |
+---------+------------+-------+
| "Space" | "edges" | 233 |
+---------+------------+-------+
15.6.13 SHOW TAGS/EDGES
SHOW TAGS
语句显示当前图空间内的所有标签。SHOW EDGES
语句显示当前图空间内的所有边类型。
nebula> SHOW TAGS;
+----------+
| Name |
+----------+
| "player" |
+----------+
| "star" |
+----------+
| "team" |
+----------+
nebula> SHOW EDGES;
+---------+
| Name |
+---------+
| "like" |
+---------+
| "serve" |
+---------+
15.6.14 SHOW USERS
显示用户信息。只有GOD角色的用户(即root)才能执行SHOW USERS语句。
nebula> SHOW USERS;
+---------+
| Account |
+---------+
| "root" |
+---------+
| "user1" |
+---------+
十六 常用语句
16.1全局操作
//执行统计任务后,查询图空间统计信息
SUBMIT JOB STATS
SHOW STATS
// 统计对应Tag的数量
LOOKUP ON memberTag | YIELD COUNT(*) as member_number;
16.2点查询(MATCH)
注意:MATCH依赖索引
// 遍历对应Tag的所有点,返回所有列信息, 点上需要建有索引
MATCH (v:memberTag) RETURN v
// 按条件查询会员(查点) 返回指定列 需要查询列为索引
MATCH (v:memberTag) where v.mobile in ['16675119413'] RETURN v.id;
//返回所有列
MATCH (v:memberTag) where v.mobile in ['16675119413'] RETURN v;
// 按条件查询会员(查点) 返回指定列 需要查询列为索引
MATCH (v:memberTag{mobile:"16675119413"}) RETURN v;
// 按条件查询群(查点) 需要查询列为索引
MATCH (v:friendsGroupTag) where v.groupName in ['就是玩'] RETURN v.groupName;
// tags:返回点的标签 properties:接收点或边并返回其属性
MATCH (a:memberTag) WHERE id(a) == "273" RETURN tags(a), properties(a);
// 不指定TAG查询点
MATCH (v) WHERE id(v) == '273' RETURN v;
// 按条件查询点,再查询该点的所有边(有方向) -- --> <--
MATCH p=(v:memberTag{mobile:"16675119413"})-->(v2) RETURN p;
16.3点查询(FETCH)
注意:不依赖索引
// 按ID查询会员(查点) 返回所有列
FETCH PROP ON memberTag "273";
//指定多个点ID获取多个点的属性值
FETCH PROP ON memberTag "273","3","54";
// 按ID查询会员(查点) 返回指定列
FETCH PROP ON memberTag "273" YIELD memberTag.mobile as mobile,memberTag.nickName as nickName;
16.4点查询(LOOKUP)
注意:
1、LOOKUP依赖索引
2、LOOKUP可查点也可以查边,但都依赖于索引
// 遍历对应Tag的所有点,只返回ID,点上需要建有索引
LOOKUP ON memberTag;
// 统计对应Tag的数量
LOOKUP ON memberTag | YIELD COUNT(*) AS member_number;
// 按条件查询会员(查点) 返回指定列 需要查询列为索引
LOOKUP ON memberTag WHERE memberTag.mobile == '16675119413';
// 按条件查询会员(查点) 返回指定列
LOOKUP ON memberTag WHERE memberTag.mobile == '16675119413' YIELD memberTag.markId, memberTag.nickName;
16.5 边查询(GO FROM)
注意:不依赖索引
//查询273关注的人 (正向查询)
GO FROM '273' OVER focusEdge;
//查询关注273的人 (反向查询)
GO FROM '273' OVER focusEdge REVERSELY;
//查询273关注的人 & 关注273的人 (双向查询)
GO FROM '273' OVER focusEdge BIDIRECT;
//查询群成员(查边)
GO FROM 'XX12535911' OVER friendsGroupEdge REVERSELY;
//查询273的好友(查边)
GO FROM '273' OVER friendsEdge;
// 查询边 返回指定列
GO FROM '273' OVER focusEdge YIELD focusEdge._src as id ,focusEdge._dst as dst,focusEdge._rank as rank,focusEdge._type as type,focusEdge.relation as relation;
// 查询1跳:返回结果273 (数据关系:54关注273,273关注102、300)
GO 1 STEPS FROM "54" OVER focusEdge;
// 查询2跳:返回结果102,300(数据关系:54关注273,273关注102、300)
GO 2 STEPS FROM "54" OVER focusEdge;
16.6边查询(FETCH)
FETCH PROP ON focusEdge "54" -> "273";
FETCH PROP ON focusEdge "54" -> "273" YIELD focusEdge._src;