官网:Nebula Graph Database 手册 (nebula-graph.com.cn)
论坛:https://discuss.nebula-graph.com.cn/
spark-connector: https://docs.nebula-graph.com.cn/2.6.1/nebula-spark-connector/
集群版:192.168.11.73,192.168.11.74,192.168.11.75
http://192.168.11.75:7001/ HOST: 192.168.11.75:9669 用户名:root 密码:123
单机版: 192.168.13.82
http://192.168.13.82:7001/ HOST: 192.168.3.82:9669 用户名:root 密码:123
2. nebula graph简介 2.1 什么是Nebula Graph Nebula Graph是一款开源的、分布式的、易扩展的原生图数据库,能够承载数千亿个点和数万亿条边的超大规模数据集,并且提供毫秒级查询。
图数据库是专门存储庞大的图形网络并从中检索信息的数据库。它可以将图中的数据高效存储为点(Vertex)和边(Edge),还可以将属性(Property)附加到点和边上。
图数据库适合存储大多数从现实抽象出的数据类型。世界上几乎所有领域的事物都有内在联系,像关系型数据库这样的建模系统会提取实体之间的关系,并将关系单独存储到表和列中,而实体的类型和属性存储在其他列甚至其他表中,这使得数据管理费时费力。
Nebula Graph作为一个典型的图数据库,可以将丰富的关系通过边及其类型和属性自然地呈现。
2.1.2 Nebula Graph的优势 开源 ,高性能 , 易扩展 , 易开发 , 高可靠访问控制 , 生态多样化 , 兼容openCypher 查询语言 , 灵活数据建模 , 广受欢迎
2.1.3 适用场景 欺诈检测 , 实时推荐 , 知识图谱 , 社交网络
3. 下载与安装nebula graph此处只讲物理机安装,docker安装请参照官网https://docs.nebula-graph.com.cn/2.6.1/2.quick-start/2.install-nebula-graph/
3.1 下载安装包 3.1.1 URL格式如下://Centos 7 https://oss-cdn.nebula-graph.com.cn/package//nebula-graph- .el7.x86_64.rpm //Centos 8 https://oss-cdn.nebula-graph.com.cn/package/ /nebula-graph- .el8.x86_64.rpm //Ubuntu 1604 https://oss-cdn.nebula-graph.com.cn/package/ /nebula-graph- .ubuntu1604.amd64.deb //Ubuntu 1804 https://oss-cdn.nebula-graph.com.cn/package/ /nebula-graph- .ubuntu1804.amd64.deb //Ubuntu 2004 https://oss-cdn.nebula-graph.com.cn/package/ /nebula-graph- .ubuntu2004.amd64.deb
例如要下载适用于Centos 7.5的2.6.1安装包:
wget https://oss-cdn.nebula-graph.com.cn/package/2.6.1/nebula-graph-2.6.1.el7.x86_64.rpm wget https://oss-cdn.nebula-graph.com.cn/package/2.6.1/nebula-graph-2.6.1.el7.x86_64.rpm.sha256sum.txt
下载适用于ubuntu 1804的2.6.1安装包:
wget https://oss-cdn.nebula-graph.com.cn/package/2.6.1/nebula-graph-2.6.1.ubuntu1804.amd64.deb wget https://oss-cdn.nebula-graph.com.cn/package/2.6.1/nebula-graph-2.6.1.ubuntu1804.amd64.deb.sha256sum.txt
3.1.2 查看虚拟机内核版本
lsb_release -a => No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 18.04.1 LTS Release: 18.04 Codename: bionic
3.1.3 下地址拼接
wget https://oss-cdn.nebula-graph.com.cn/package/2.6.1/nebula-graph-2.6.1.ubuntu1804.amd64.deb3.2 安装Nebula Graph 3.2.1 在默认路径下安装
sudo dpkg -i nebula-graph-2.6.1.ubuntu1804.amd64.deb
如果不设置安装路径,默认安装路径为/usr/local/nebula/
3.2.2 指定安装路径sudo dpkg -i --instdir==/home/intellif/nebula nebula-graph-2.6.1.ubuntu1804.amd64.deb
指定安装目录为 /home/intellif/nebula
3.3 修改配置文件cd /usr/local/nebula/etc 修改:nebula-graphd.conf,nebula-metad.conf,nebula-storaged.conf 将文件中127.0.0.1/0.0.0.0换成本地ip地址192.168.13.82 须在配置文件中使用真实的 IP 地址。否则某些情况下127.0.0.1/0.0.0.0无法正确解析
一定修改ip地址,不然会导致后续写入可以成功但是读取报错。使用spark-connector始终无法读取Nebula Graph数据,抛出ExecuteFailedException: Execute failed: no parts succeed, error message: Unable to activate object
3.4 卸载DEB 包安装的 Nebula Graph-
使用如下命令查看 Nebula Graph 版本。
$ dpkg -l | grep "nebula"
返回类似如下结果。
ii nebula-graph 2.6.1 amd64 Nebula Package built using CMake
-
使用如下命令卸载 Nebula Graph。
sudo dpkg -r
例如:
sudo dpkg -r nebula-graph
-
删除安装目录。
Nebula Graph使用脚本nebula.service管理服务,包括启动、停止、重启、中止和查看。
nebula.service的默认路径是/usr/local/nebula/scripts,如果修改过安装路径,请使用实际路径。
语法:
$ sudo /usr/local/nebula/scripts/nebula.service [-v] [-c]
| 参数 | 说明 |
|---|---|
| -v | 显示详细调试信息。 |
| -c | 指定配置文件路径,默认路径为/usr/local/nebula/etc/。 |
| start | 启动服务。 |
| stop | 停止服务。 |
| restart | 重启服务。 |
| kill | 中止服务。 |
| status | 查看服务状态。 |
| metad | 管理meta服务。 |
| graphd | 管理Graph服务。 |
| storaged | 管理Storage服务。 |
| all | 管理所有服务。 |
sudo /usr/local/nebula/scripts/nebula.service start all4.2 停止所有服务
sudo /usr/local/nebula/scripts/nebula.service stop all4.3 查看所有服务
sudo /usr/local/nebula/scripts/nebula.service status all5. 连接Nebula Graph服务 5.1 前提条件
-
Nebula Graph服务已启动。
-
运行Nebula Console的机器和运行Nebula Graph的服务器网络互通。
-
在Nebula Console下载页面,确认需要的版本,单击Assets。
-
在Assets区域找到机器运行所需的二进制文件,下载文件到机器上
下载: nebula-console-linux-amd64-v2.6.1
-
(可选)为方便使用,重命名文件为nebula-console。
-
在运行Nebula Console的机器上执行如下命令,为用户授予nebula-console文件的执行权限。
-
在命令行界面中,切换工作目录至nebula-console文件所在目录。
-
执行如下命令连接Nebula Graph。
./nebula-console -addr
-port -u -p [-t 120] [-e "nGQL_statement" | -f filename.nGQL]
| 参数 | 说明 |
|---|---|
| -h | 显示帮助菜单。 |
| -addr | 设置要连接的graphd服务的IP地址。默认地址为127.0.0.1。 |
| -port | 设置要连接的graphd服务的端口。默认端口为9669。 |
| -u/-user | 设置Nebula Graph账号的用户名。未启用身份认证时,可以使用任意已存在的用户名(默认为root)。 |
| -p/-password | 设置用户名对应的密码。未启用身份认证时,密码可以填写任意字符。 |
| -t/-timeout | 设置整数类型的连接超时时间。单位为秒,默认值为120。 |
| -e/-eval | 设置字符串类型的nGQL语句。连接成功后会执行一次该语句并返回结果,然后自动断开连接。 |
| -f/-file | 设置存储nGQL语句的文件的路径。连接成功后会执行该文件内的nGQL语句并返回结果,执行完毕后自动断开连接。 |
例如:
./nebula-console -addr 192.168.13.82 -port 9669 -u root -p 123 -t 120
连接后可以使用./nebula-console --help命令获取所有参数的说明,也可以在项目仓库找到更多说明。
6. 安装Nebula Graph StudioNebula Graph Studio(简称 Studio)是一款可以通过 Web 访问的图数据库开源可视化工具,搭配 Nebula Graph 内核使用,提供构图、数据导入、编写 nGQL 查询、图探索等一站式服务。
6.1 tar 包部署 Studio 6.1.1 前提条件 在部署 tar 包安装的 Studio 之前,用户需要确认以下信息:
-
Nebula Graph 服务已经部署并启动。详细信息,参考Nebula Graph安装部署。
-
使用的 Linux 上安装有版本为 v10.12.0 以上的 Node.js。
linux下npm和node的升级
安装 npm nodejs
sudo npm i -g npm
1. 查看版本
npm -v
6.14.2
node -v
v8.11.2
1. . npm升级
升级到最新版本
sudo npm i -g npm
升级到指定版本
sudo npm i -g npm@8.11.2
1. node升级(不可以升级到最新版本 v17.0.1)
sudo npm i -g n
安装指定版本
sudo n v14.18.1 -
确保在安装开始前,以下端口处于未被使用状态。
| 端口号 | 说明 |
|---|---|
| 7001 | Studio提供的web服务 |
| 8080 | Nebula-http-gateway,Client的HTTP服务 |
-
根据需要下载 tar 包,建议选择最新版本。
安装包 Studio 版本 nebula-graph-studio-3.1.0.x86_64.tar.gz 3.1.0 -
使用 tar -xvf 解压 tar 包。
tar -xvf nebula-graph-studio-3.1.0.x86_64.tar.gz
-
部署 nebula-http-gateway 并启动。
$ cd nebula-http-gateway $ nohup ./nebula-httpd &
查看nebula-httpd服务是否启动成功: ps -ef | grep nebula-httpd
如果没有启动成功则页面会显示: 请求错误:504 Gateway Timeout
-
部署 nebula-graph-studio 并启动。
$ cd nebula-graph-studio $ npm run start
-
启动成功后,在浏览器地址栏输入 http://ip address:7001。
如果在浏览器窗口中能看到以下登录界面,表示已经成功部署并启动 Studio。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JE9zPOWz-1641536818397)(studio登入页面.png)]
6.2 停止服务 用户可以采用 kill pid 的方式来关停服务:
kill $(lsof -t -i :8080) # stop nebula-http-gateway cd nebula-graph-studio npm run stop # stop nebula-graph-studio6.3 连接数据库 6.3.1 Host
填写 Nebula Graph 的 Graph 服务本机 IP 地址及端口。格式为 ip:port。如果端口未修改,则使用默认端口 9669。
即使 Nebula Graph 数据库与 Studio 部署在同一台机器上,用户也必须在 Host 字段填写这台机器的本机 IP 地址,而不是 127.0.0.1 或者 localhost。
6.3.2 用户名和密码根据 Nebula Graph 的身份验证设置填写登录账号和密码。
- 如果未启用身份验证,可以填写默认用户名 root 和任意密码。
- 如果已启用身份验证,但是未创建账号信息,用户只能以 GOD 角色登录,必须填写 root 及对应的密码 nebula。
- 如果已启用身份验证,同时又创建了不同的用户并分配了角色,不同角色的用户使用自己的账号和密码登录。
例如:
Host: 192.168.13.82:9669 用户名:root 密码: 1234566.4 部署多机集群 6.4.1 部署方案
准备5台用于部署集群的机器
| 机器名称 | IP 地址 | graphd 进程数量 | storaged 进程数量 | metad 进程数量 |
|---|---|---|---|---|
| A | 192.168.10.111 | 1 | 1 | 1 |
| B | 192.168.10.112 | 1 | 1 | 1 |
| C | 192.168.10.113 | 1 | 1 | 1 |
| D | 192.168.10.114 | 1 | 1 | - |
| E | 192.168.10.115 | 1 | 1 | - |
-
安装nebula Graph
在集群的每台服务器上都安装nebula Graph,安装后暂不需要启动服务。
-
修改配置文件
修改每个服务器上的nebula Graph配置文件。
Nebula Graph的所有配置文件均位于安装目录的etc目录内,包括nebula-graphd.conf、nebula-metad.conf和nebula-storaged.conf,用户可以只修改所需服务的配置文件。各个机器需要修改的配置文件如下。
机器名称 待修改配置文件 A nebula-graphd.conf、nebula-storaged.conf、nebula-metad.conf B nebula-graphd.conf、nebula-storaged.conf、nebula-metad.conf C nebula-graphd.conf、nebula-storaged.conf、nebula-metad.conf D nebula-graphd.conf、nebula-storaged.conf E nebula-graphd.conf、nebula-storaged.conf
机器A的配置:
- nebula-graphd.conf
########## networking ########## # Comma separated meta Server Addresses --meta_server_addrs=192.168.10.111:9559,192.168.10.112:9559,192.168.10.113:9559 # Local IP used to identify the nebula-graphd process. # Change it to an address other than loopback if the service is distributed or # will be accessed remotely. --local_ip=192.168.10.111 # Network device to listen on --listen_netdev=any # Port to listen on --port=9669
- nebula-storaged.conf
########## networking ########## # Comma separated meta server addresses --meta_server_addrs=192.168.10.111:9559,192.168.10.112:9559,192.168.10.113:9559 # Local IP used to identify the nebula-storaged process. # Change it to an address other than loopback if the service is distributed or # will be accessed remotely. --local_ip=192.168.10.111 # Storage daemon listening port --port=9779
- nebula-metad.conf
########## networking ########## # Comma separated meta Server addresses --meta_server_addrs=192.168.10.111:9559,192.168.10.112:9559,192.168.10.113:9559 # Local IP used to identify the nebula-metad process. # Change it to an address other than loopback if the service is distributed or # will be accessed remotely. --local_ip=192.168.10.111 # meta daemon listening port --port=9559
机器 B 配置
-
nebula-graphd.conf
########## networking ########## # Comma separated meta Server Addresses --meta_server_addrs=192.168.10.111:9559,192.168.10.112:9559,192.168.10.113:9559 # Local IP used to identify the nebula-graphd process. # Change it to an address other than loopback if the service is distributed or # will be accessed remotely. --local_ip=192.168.10.112 # Network device to listen on --listen_netdev=any # Port to listen on --port=9669
-
nebula-storaged.conf
########## networking ########## # Comma separated meta server addresses --meta_server_addrs=192.168.10.111:9559,192.168.10.112:9559,192.168.10.113:9559 # Local IP used to identify the nebula-storaged process. # Change it to an address other than loopback if the service is distributed or # will be accessed remotely. --local_ip=192.168.10.112 # Storage daemon listening port --port=9779
-
nebula-metad.conf
########## networking ########## # Comma separated meta Server addresses --meta_server_addrs=192.168.10.111:9559,192.168.10.112:9559,192.168.10.113:9559 # Local IP used to identify the nebula-metad process. # Change it to an address other than loopback if the service is distributed or # will be accessed remotely. --local_ip=192.168.10.112 # meta daemon listening port --port=9559
机器 C 配置
-
nebula-graphd.conf
########## networking ########## # Comma separated meta Server Addresses --meta_server_addrs=192.168.10.111:9559,192.168.10.112:9559,192.168.10.113:9559 # Local IP used to identify the nebula-graphd process. # Change it to an address other than loopback if the service is distributed or # will be accessed remotely. --local_ip=192.168.10.113 # Network device to listen on --listen_netdev=any # Port to listen on --port=9669
-
nebula-storaged.conf
########## networking ########## # Comma separated meta server addresses --meta_server_addrs=192.168.10.111:9559,192.168.10.112:9559,192.168.10.113:9559 # Local IP used to identify the nebula-storaged process. # Change it to an address other than loopback if the service is distributed or # will be accessed remotely. --local_ip=192.168.10.113 # Storage daemon listening port --port=9779
-
nebula-metad.conf
########## networking ########## # Comma separated meta Server addresses --meta_server_addrs=192.168.10.111:9559,192.168.10.112:9559,192.168.10.113:9559 # Local IP used to identify the nebula-metad process. # Change it to an address other than loopback if the service is distributed or # will be accessed remotely. --local_ip=192.168.10.113 # meta daemon listening port --port=9559
机器 D 配置
-
nebula-graphd.conf
########## networking ########## # Comma separated meta Server Addresses --meta_server_addrs=192.168.10.111:9559,192.168.10.112:9559,192.168.10.113:9559 # Local IP used to identify the nebula-graphd process. # Change it to an address other than loopback if the service is distributed or # will be accessed remotely. --local_ip=192.168.10.114 # Network device to listen on --listen_netdev=any # Port to listen on --port=9669
-
nebula-storaged.conf
########## networking ########## # Comma separated meta server addresses --meta_server_addrs=192.168.10.111:9559,192.168.10.112:9559,192.168.10.113:9559 # Local IP used to identify the nebula-storaged process. # Change it to an address other than loopback if the service is distributed or # will be accessed remotely. --local_ip=192.168.10.114 # Storage daemon listening port --port=9779
机器 E 配置
-
nebula-graphd.conf
########## networking ########## # Comma separated meta Server Addresses --meta_server_addrs=192.168.10.111:9559,192.168.10.112:9559,192.168.10.113:9559 # Local IP used to identify the nebula-graphd process. # Change it to an address other than loopback if the service is distributed or # will be accessed remotely. --local_ip=192.168.10.115 # Network device to listen on --listen_netdev=any # Port to listen on --port=9669
-
nebula-storaged.conf
########## networking ########## # Comma separated meta server addresses --meta_server_addrs=192.168.10.111:9559,192.168.10.112:9559,192.168.10.113:9559 # Local IP used to identify the nebula-storaged process. # Change it to an address other than loopback if the service is distributed or # will be accessed remotely. --local_ip=192.168.10.115 # Storage daemon listening port --port=9779
依次启动各个服务器上的对应进程。
| 机器名称 | 待启动的进程 |
|---|---|
| A | graphd、storaged、metad |
| B | graphd、storaged、metad |
| C | graphd、storaged、metad |
| D | graphd、storaged |
| E | graphd、storaged |
启动 Nebula Graph 进程的命令如下:
sudo /usr/local/nebula/scripts/nebula.service start6.4.4 检查集群
安装原生CLI客户端Nebula Console,然后连接任何一个已启动graphd进程的机器
$ ./nebula-console --addr 192.168.10.111 --port 9669 -u root -p nebula 2021/05/25 01:41:19 [INFO] connection pool is initialized successfully Welcome to Nebula Graph! > SHOW HOSTS; +------------------+------+----------+--------------+----------------------+------------------------+ | Host | Port | Status | Leader count | Leader distribution | Partition distribution | +------------------+------+----------+--------------+----------------------+------------------------+ | "192.168.10.111" | 9779 | "ONLINE" | 0 | "No valid partition" | "No valid partition" | | "192.168.10.112" | 9779 | "ONLINE" | 0 | "No valid partition" | "No valid partition" | | "192.168.10.113" | 9779 | "ONLINE" | 0 | "No valid partition" | "No valid partition" | | "192.168.10.114" | 9779 | "ONLINE" | 0 | "No valid partition" | "No valid partition" | | "192.168.10.115" | 9779 | "ONLINE" | 0 | "No valid partition" | "No valid partition" | | "Total" | | | 0 | | | +------------------+------+----------+--------------+----------------------+------------------------+7. 常用命令 nGQL 7.1 创建和选择图空间 7.1.1 创建
CREATE SPACE [IF NOT EXISTS]( [partition_num = ,] [replica_factor = ,] vid_type = {FIXED_STRING( ) | INT[64]} ) [ON ] [COMMENT = ' '];
| 参数 | 说明 |
|---|---|
| IF NOT EXISTS | 检测待创建的图空间是否存在,只有不存在时,才会创建图空间。仅检测图空间的名称,不会检测具体属性。 |
| 在Nebula Graph实例中唯一标识一个图空间。图空间名称由大小写英文字母、数字或下划线组成,区分大写小,且不可使用关键字和保留字。 | |
| partition_num | 指定图空间的分片数量。建议设置为5倍的集群硬盘数量。例如集群中有3个硬盘,建议设置15个分片。默认值为100。 |
| replica_factor | 指定每个分片的副本数量。建议在生产环境中设置为3,在测试环境中设置为1。由于需要基于多数表决,副本数量必须是奇数。默认值为1。 |
| vid_type | 必选参数。指定点ID的数据类型。可选值为FIXED_STRING( |
| ON | 指定图空间所属的Group。详情请参见Group&Zone。 |
| COMMENT | 图空间的描述。最大为256字节。默认无描述。 |
备注 :
- 如果将副本数设置为1,用户将无法使用BALANCE命令为Nebula Graph的存储服务平衡负载或扩容。
- 在Nebula Graph 1.x中,VID的类型只能为INT64,不支持字符型;在Nebula Graph 2.x中, VID的类型支持INT64和FIXED_STRING(
)。请在创建图空间时指定VID类型,使用INSERT语句时也需要保持一致,否则会报错VID类型不匹配Wrong vertex id type: 1001。 - VID最大长度必须为N,不可任意长度;超过该长度也会报错The VID must be a 64-bit integer or a string fitting space vertex id length limit.。
例如:
CREATE SPACE basketballplayer(partition_num=15,replica_factor=1,vid_type=fixed_string(30)); create space test1(partition_num=20,replica_factor=1,vid_type=fixed_string(30)) comment = '测试1';7.1.2 使用
USE7.1.3 显示所有space; 例如:use test1;
SHOW SPACES;7.1.4 显示space的详细信息
DESC[RIBE] SPACE7.1.5 删除space; 例如: desc space test1
DROp SPACE [IF EXISTS]; 例如: drop space if exists test1;
IF EXISTS关键字可以检测待删除的图空间是否存在,只有存在时,才会删除图空间。
DROP SPACE语句不会立刻删除硬盘上对应图空间的目录和文件,请使用USE语句指定其他任意图空间,然后执行SUBMIT JOB COMPACT
7.2 顶点TAG 7.2.1 创建 创建Tag前,需要先用USE语句指定工作空间。
CREATE TAG [IF NOT EXISTS]( [NULL | NOT NULL] [DEFAULT ] [COMMENT ' '] [{, [NULL | NOT NULL] [DEFAULT ] [COMMENT ' ']} ...] ) [TTL_DURATION = ] [TTL_COL = ] [COMMENT = ' '];
| 参数 | 说明 |
|---|---|
| IF NOT EXISTS | 检测待创建的Tag是否存在,只有不存在时,才会创建Tag。仅检测Tag的名称,不会检测具体属性。 |
| 每个图空间内的Tag必须是唯一的。Tag名称设置后无法修改。Tag名称由大小写英文字母、数字或下划线组成,区分大写小,且不可使用关键字和保留字。 | |
| 属性名称。每个Tag中的属性名称必须唯一。属性的命名规则与Tag相同。 | |
| 属性的数据类型,目前支持数值、布尔、字符串以及日期与时间。 | |
| NULL | NOT NULL | 指定属性值是否支持为NULL。默认值为NULL。 |
| DEFAULT | 指定属性的默认值。默认值可以是一个文字值或Nebula Graph支持的表达式。如果插入点时没有指定某个属性的值,则使用默认值。 |
| COMMENT | 对单个属性或Tag的描述。最大为256字节。默认无描述。 |
| TTL_DURATION | 指定属性存活时间。超时的属性将会过期。属性值和时间戳差值之和如果小于当前时间戳,属性就会过期。默认值为0,表示属性永不过期。 |
| TTL_COL | 指定要设置存活时间的属性。属性的数据类型必须是int或者timestamp。一个Tag只能指定一个字段为TTL_COL。更多TTL的信息请参见TTL。 |
例如:
CREATE TAG IF NOT EXISTS player(name string, age int); # 创建没有属性的Tag CREATE TAG IF NOT EXISTS no_property(); # 创建包含默认值的Tag CREATE TAG IF NOT EXISTS player_with_default(name string, age int DEFAULT 20); # 对字段create_time设置TTL为100秒 CREATE TAG IF NOT EXISTS woman(name string, age int,married bool, salary double, create_time timestamp) TTL_DURATION = 100, TTL_COL = "create_time";7.2.2 删除
前提条件
-
登录的用户必须拥有对应权限才能执行DROP TAG语句。详情请参见内置角色权限。
-
确保Tag不包含任何索引,否则DROP TAG时会报冲突错误[ERROR (-8)]: Conflict!。删除索引请参见drop index。
语法
DROP TAG [IF EXISTS];
-
IF EXISTS:检测待删除的Tag是否存在,只有存在时,才会删除Tag。
-
tag_name:指定要删除的Tag名称。一次只能删除一个Tag。
示例
nebula> CREATE TAG IF NOT EXISTS test(p1 string, p2 int); nebula> DROP TAG test;7.2.3 修改
ALTER TAG语句可以修改Tag的结构。例如增删属性、修改数据类型,也可以为属性设置、修改TTL(Time-To-Live)。
前提条件:
-
登录的用户必须拥有对应权限才能执行ALTER TAG语句。详情请参见内置角色权限。
-
确保要修改的属性不包含索引,否则ALTER TAG时会报冲突错误[ERROR (-8)]: Conflict!。删除索引请参见drop index。
语法:
ALTER TAG[[, alter_definition] ...] [ttl_definition [, ttl_definition] ... ] [COMMENT = ' ']; alter_definition: | ADD (prop_name data_type) | DROP (prop_name) | CHANGE (prop_name data_type) ttl_definition: TTL_DURATION = ttl_duration, TTL_COL = prop_name
-
tag_name:指定要修改的Tag名称。一次只能修改一个Tag。请确保要修改的Tag在当前工作空间中存在,否则会报错。
-
可以在一个ALTER TAG语句中使用多个ADD、DROP和CHANGE子句,子句之间用英文逗号(,)分隔。
示例:
nebula> CREATE TAG IF NOT EXISTS t1 (p1 string, p2 int); nebula> ALTER TAG t1 ADD (p3 int, p4 string); nebula> ALTER TAG t1 TTL_DURATION = 2, TTL_COL = "p2"; nebula> ALTER TAG t1 COMMENT = 'test1';7.2.4 显示所有tag
SHOW TAGS语句显示当前图空间内的所有Tag名称。
执行SHOW TAGS语句不需要任何权限,但是返回结果由登录的用户权限决定。
语法:
SHOW TAGS;7.2.5 显示tag的详细
DESCRIBE TAG显示指定Tag的详细信息,例如字段名称、数据类型等。
前提条件:
登录的用户必须拥有对应权限才能执行DESCRIBE TAG语句。详情请参见内置角色权限。
语法:
DESC[RIBE] TAG;
DESCRIBE可以缩写为DESC。
示例:
DESCRIBE TAG player;7.2.6 删除tag
DELETE TAG语句可以删除指定点上的指定Tag。
点可以有一个或多个Tag。
-
如果某个点只有一个Tag,删除这个点上的Tag后,用户就无法访问这个点,下次Compaction操作时会删除该点,但点上的边仍然存在。
-
如果某个点有多个Tag,删除其中一个Tag,仍然可以访问这个点,但是无法访问这个点上已删除Tag所定义的所有属性。
前提条件:
登录的用户必须拥有对应权限才能执行DELETE TAG语句。详情请参见内置角色权限。
语法:
DELETE TAGFROM ;
-
tag_name_list:指定Tag名称。多个Tag用英文逗号(,)分隔,也可以用*表示所有Tag。
-
VID:指定要删除Tag的点ID。
示例:
nebula> CREATE TAG IF NOT EXISTS test1(p1 string, p2 int);
nebula> CREATE TAG IF NOT EXISTS test2(p3 string, p4 int);
nebula> INSERT VERTEX test1(p1, p2),test2(p3, p4) VALUES "test":("123", 1, "456", 2);
nebula> FETCH PROP ON * "test";
+------------------------------------------------------------+
| vertices_ |
+------------------------------------------------------------+
| ("test" :test2{p3: "456", p4: 2} :test1{p1: "123", p2: 1}) |
+------------------------------------------------------------+
nebula> DELETe TAG test1 FROM "test";
nebula> FETCH PROP ON * "test";
+-----------------------------------+
| vertices_ |
+-----------------------------------+
| ("test" :test2{p3: "456", p4: 2}) |
+-----------------------------------+
nebula> DELETe TAG * FROM "test";
nebula> FETCH PROP ON * "test";
7.2.7 增加和删除标签
在openCypher中,有增加标签(SET label)和移除标签(REMOVE label)的功能,可以用于加速查询或者标记过程。
在Nebula Graph中,可以通过Tag变相实现相同操作,创建Tag并将Tag插入到已有的点上,就可以根据Tag名称快速查找点,也可以通过DELETe TAG删除某些点上不再需要的Tag。
Caution
请确保点上已经有另一个Tag,否则删除点上最后一个Tag时,会导致点也被删除。
示例:
例如在basketballplayer数据集中,部分篮球运动员同时也是球队股东,可以为股东Tagshareholder创建索引,方便快速查找。如果不再是股东,可以通过DELETE TAG语句删除相应运动员的股东Tag。
//创建股东Tag和索引
nebula> CREATE TAG IF NOT EXISTS shareholder();
nebula> CREATE TAG INDEX IF NOT EXISTS shareholder_tag on shareholder();
//为点添加Tag
nebula> INSERT VERTEX shareholder() VALUES "player100":();
nebula> INSERT VERTEX shareholder() VALUES "player101":();
//快速查询所有股东
nebula> MATCH (v:shareholder) RETURN v;
+---------------------------------------------------------------------+
| v |
+---------------------------------------------------------------------+
| ("player100" :player{age: 42, name: "Tim Duncan"} :shareholder{}) |
| ("player101" :player{age: 36, name: "Tony Parker"} :shareholder{}) |
+---------------------------------------------------------------------+
nebula> LOOKUP ON shareholder;
+-------------+
| VertexID |
+-------------+
| "player100" |
| "player101" |
+-------------+
//如果player100不再是股东
nebula> DELETE TAG shareholder FROM "player100";
nebula> LOOKUP ON shareholder;
+-------------+
| VertexID |
+-------------+
| "player101" |
+-------------+
备注:
如果插入测试数据后才创建索引,请用REBUILD TAG INDEX
语法:
创建Edge type前,需要先用USE语句指定工作空间。
CREATE EDGE [IF NOT EXISTS]( [NULL | NOT NULL] [DEFAULT ] [COMMENT ' '] [{, [NULL | NOT NULL] [DEFAULT ] [COMMENT ' ']} ...] ) [TTL_DURATION = ] [TTL_COL = ] [COMMENT = ' '];
| 参数 | 说明 |
|---|---|
| IF NOT EXISTS | 检测待创建的Edge type是否存在,只有不存在时,才会创建Edge type。仅检测Edge type的名称,不会检测具体属性。 |
| 每个图空间内的Edge type必须是唯一的。Edge type名称设置后无法修改。Edge type名称由大小写英文字母、数字或下划线组成,区分大写小,且不可使用关键字和保留字。 | |
| 属性名称。每个Edge type中的属性名称必须唯一。属性的命名规则与Edge type相同。 | |
| 属性的数据类型,目前支持数值、布尔、字符串以及日期与时间。 | |
| NULL | NOT NULL | 指定属性值是否支持为NULL。默认值为NULL。 |
| DEFAULT | 指定属性的默认值。默认值可以是一个文字值或Nebula Graph支持的表达式。如果插入边时没有指定某个属性的值,则使用默认值。 |
| COMMENT | 对单个属性或Edge type的描述。最大为256字节。默认无描述。 |
| TTL_DURATION | 指定属性存活时间。超时的属性将会过期。属性值和时间戳差值之和如果小于当前时间戳,属性就会过期。默认值为0,表示属性永不过期。 |
| TTL_COL | 指定要设置存活时间的属性。属性的数据类型必须是int或者timestamp。一个Edge type只能指定一个字段为TTL_COL。更多TTL的信息请参见TTL。 |
示例:
nebula> CREATE EDGE IF NOT EXISTS follow(degree int);
# 创建没有属性的Edge type。
nebula> CREATE EDGE IF NOT EXISTS no_property();
# 创建包含默认值的Edge type。
nebula> CREATE EDGE IF NOT EXISTS follow_with_default(degree int DEFAULT 20);
# 对字段p2设置TTL为100秒。
nebula> CREATE EDGE IF NOT EXISTS e1(p1 string, p2 int, p3 timestamp)
TTL_DURATION = 100, TTL_COL = "p2";
7.3.2 删除
DROp EDGE语句可以删除当前工作空间内的指定Edge type。
一个边只能有一个Edge type,删除这个Edge type后,用户就无法访问这个边,下次Compaction操作时会删除该边。
删除Edge type操作仅删除Schema数据,硬盘上的文件或目录不会立刻删除,而是在下一次Compaction操作时删除。
前提条件:
-
登录的用户必须拥有对应权限才能执行DROP EDGE语句。详情请参见内置角色权限。
-
确保Edge type不包含任何索引,否则DROP EDGE时会报冲突错误[ERROR (-8)]: Conflict!。删除索引请参见drop index。
语法:
DROP EDGE [IF EXISTS]
-
IF EXISTS:检测待删除的Edge type是否存在,只有存在时,才会删除Edge type。
-
edge_type_name:指定要删除的Edge type名称。一次只能删除一个Edge type。
示例:
nebula> CREATE EDGE IF NOT EXISTS e1(p1 string, p2 int); nebula> DROP EDGE e1;7.3.3 修改
ALTER EDGE语句可以修改Edge type的结构。例如增删属性、修改数据类型,也可以为属性设置、修改TTL(Time-To-Live)。
前提条件:
- 确保要修改的属性不包含属性,否则ALTER EDGE 时会报冲突错误 [ERROR (-8)]: Conflict!。删除索引请参见drop index。
语法:
ALTER EDGE']; alter_definition: | ADD (prop_name data_type) | DROP (prop_name) | CHANGE (prop_name data_type) ttl_definition: TTL_DURATION = ttl_duration, TTL_COL = prop_name
-
edge_type_name:指定要修改的Edge type名称。一次只能修改一个Edge type。请确保要修改的Edge type在当前工作空间中存在,否则会报错。
-
可以在一个ALTER EDGE语句中使用多个ADD、DROP和CHANGE子句,子句之间用英文逗号(,)分隔。
示例:
nebula> CREATE EDGE IF NOT EXISTS e1(p1 string, p2 int); nebula> ALTER EDGE e1 ADD (p3 int, p4 string); nebula> ALTER EDGE e1 TTL_DURATION = 2, TTL_COL = "p2"; nebula> ALTER EDGE e1 COMMENT = 'edge1';
修改Edge type说明:
尝试使用刚修改的Edge type可能会失败,因为修改是异步实现的。
Nebula Graph将在下一个心跳周期内完成Edge type的修改,为了确保修改成功,可以使用如下方法之一:
-
在DESCRIBE EDGE语句的结果中查看Edge type信息,确认修改成功。如果没有修改成功,请等待几秒重试。
-
等待两个心跳周期,例如20秒。
如果需要修改心跳间隔,请为所有配置文件修改参数heartbeat_interval_secs。
7.3.4 显示所有edge语法:
SHOW EDGES;7.3.5 显示edge的详细
语法:
DESC[RIBE] EDGE
DESCRIBE可以缩写为DESC。
7.4 点语句 7.4.1 插入点 INSERT VERTEXINSERT VERTEX语句可以在Nebula Graph实例的指定图空间中插入一个或多个点。
语法:
INSERT VERTEX [IF NOT EXISTS]( ) [, ( ), ...] {VALUES | VALUE} VID: ( [, ]) prop_name_list: [prop_name [, prop_name] ...] prop_value_list: [prop_value [, prop_value] ...]
- IF NOT EXISTS:用户可以使用IF NOT EXISTS关键字检测待插入的VID是否存在,只有不存在时,才会插入,如果已经存在,不会进行修改。
Note:
- IF NOT EXISTS 仅检测 VID + Tag 的值是否相同,不会检测属性值。
- IF NOT EXISTS 会先读取一次数据是否存在,因此对性能会有明显影响。
-
tag_name:点关联的Tag(点类型)。Tag必须提前创建,详情请参见CREATE TAG。
-
prop_name_list:需要设置的属性名称列表。
-
VID:点ID。在Nebula Graph 2.0中支持字符串和整数,需要在创建图空间时设置,详情请参见CREATE SPACE。
-
prop_value_list:根据prop_name_list填写属性值。如果属性值和Tag中的数据类型不匹配,会返回错误。如果没有填写属性值,而Tag中对应的属性设置为NOT NULL,也会返回错误。详情请参见CREATE TAG。
-
INSERT VERTEX与openCypher中CREATE的语意不同:
- INSERT VERTEX语意更接近于NoSQL(key-value)方式的INSERT语意,或者SQL中的UPSERT (UPDATE or INSERT)。
- 相同VID和TAG的情况下,如果没有使用IF NOT EXISTS,新写入的数据会覆盖旧数据,不存在时会新写入。
- 相同VID但不同TAG的情况下,不同TAG对应的记录不会相互覆盖,不存在会新写入。
示例:
# 插入不包含属性的点
CREATE TAG IF NOT EXISTS t1();
INSERT VERTEX t1() value "10":();
CREATE TAG IF NOT EXISTS t2 (name string,age int);
INSERT VERTEX t2 (name,age) VALUES "11":("n1" , 12)
# 一次插入2个点
INSERT VERTEX t2 (name,age) VALUES "13":( "n3" , 12),"14":("n4" , 16)
一个点可以多次插入属性值,以最后一次为准。
# 多次插入属性值。
nebula> INSERT VERTEX t2 (name, age) VALUES "11":("n2", 13);
nebula> INSERT VERTEX t2 (name, age) VALUES "11":("n3", 14);
nebula> INSERT VERTEX t2 (name, age) VALUES "11":("n4", 15);
nebula> FETCH PROP ON t2 "11";
+---------------------------------+
| vertices_ |
+---------------------------------+
| ("11" :t2{age: 15, name: "n4"}) |
+---------------------------------+
nebula> CREATE TAG IF NOT EXISTS t5(p1 fixed_string(5) NOT NULL, p2 int, p3 int DEFAULT NULL);
nebula> INSERT VERTEX t5(p1, p2, p3) VALUES "001":("Abe", 2, 3);
# 插入失败,因为属性p1不能为NULL。
nebula> INSERT VERTEX t5(p1, p2, p3) VALUES "002":(NULL, 4, 5);
[ERROR (-1005)]: Storage Error: The not null field cannot be null.
# 属性p3为默认值NULL。
nebula> INSERT VERTEX t5(p1, p2) VALUES "003":("cd", 5);
nebula> FETCH PROP ON t5 "003";
+--------------------------------------------+
| vertices_ |
+--------------------------------------------+
| ("003" :t5{p1: "cd", p2: 5, p3: __NULL__}) |
+--------------------------------------------+
# 属性p1最大长度为5,因此会被截断。
nebula> INSERT VERTEX t5(p1, p2) VALUES "004":("shalalalala", 4);
nebula> FETCH PROP on t5 "004";
+-----------------------------------------------+
| vertices_ |
+-----------------------------------------------+
| ("004" :t5{p1: "shala", p2: 4, p3: __NULL__}) |
+-----------------------------------------------+
使用IF NOT EXISTS插入已存在的点时,不会进行修改。
# 插入点1。
nebula> INSERT VERTEX t2 (name, age) VALUES "1":("n2", 13);
# 使用IF NOT EXISTS修改点1,因为点1已存在,不会进行修改。
nebula> INSERT VERTEX IF NOT EXISTS t2 (name, age) VALUES "1":("n3", 14);
nebula> FETCH PROP ON t2 "1";
+--------------------------------+
| vertices_ |
+--------------------------------+
| ("1" :t2{age: 13, name: "n2"}) |
+--------------------------------+
7.4.2 删除点 DELETE VERTEX
DELETE VERTEX 语句可以删除点,以及点关联的出边和入边。
DELETE VERTEX 语句一次可以删除一个或者多个点。可以结合管道符一起使用,详情请参见管道符。
note:
DELETE VERTEX是直接删除点和关联的边。
DELETE TAG是删除指定点上的指定Tag。当点上只有一个Tag时,执行DELETE TAG会删除点,但是不会删除关联的边。
语法:
DELETE VERTEX[ , .... ]
示例:
DELETE VERTEX "team1"; # 结合管道符,删除符合条件的点。 nebula> GO FROM "player100" OVER serve WHERe properties(edge).start_year == "2021" YIELD dst(edge) AS id | DELETe VERTEX $-.id;7.4.3 修改点属性 UPDATE VERTEX
UPDATE VERTEX语句可以修改点上Tag的属性值。
Nebula Graph支持CAS(compare and set)操作
note : 一次只能修改一个Tag。
语法:
UPDATE VERTEX ONSET [WHEN ] [YIELD
| 参数 | 是否必须 | 说明 | 示例 |
|---|---|---|---|
| ON | 是 | 指定点的Tag。要修改的属性必须在这个Tag内。 | ON player |
| 是 | 指定要修改的点ID。 | "player100" | |
| SET | 是 | 指定如何修改属性值。 | SET age = age +1 |
| WHEN | 否 | 指定过滤条件。如果 | WHEN name == "Tim" |
| YIELD | 否 | 指定语句的输出格式。 | YIELD name AS Name |
示例:
// 查看点”player101“的属性。
nebula> FETCH PROP ON player "player101";
+-----------------------------------------------------+
| vertices_ |
+-----------------------------------------------------+
| ("player101" :player{age: 36, name: "Tony Parker"}) |
+-----------------------------------------------------+
// 修改属性age的值,并返回name和新的age。
nebula> UPDATE VERTEX ON player "player101"
SET age = age + 2
WHEN name == "Tony Parker"
YIELD name AS Name, age AS Age;
+---------------+-----+
| Name | Age |
+---------------+-----+
| "Tony Parker" | 38 |
+---------------+-----+
7.4.4 存在修改,不存在创建 VERTEX
UPSERT VERTEX语句结合UPDATE和INSERT,如果点存在,会修改点的属性值;如果点不存在,会插入新的点。
note: UPSERT VERTEX一次只能修改一个Tag。
UPSERT VERTEX性能远低于INSERT,因为UPSERT是一组分片级别的读取、修改、写入操作。
note: 禁止在高并发写操作的情况下使用UPSERT语句,请使用UPDATE或INSERT代替。
语法:
UPSERT VERTEX ONSET [WHEN ] [YIELD
| 参数 | 是否必须 | 说明 | 示例 |
|---|---|---|---|
| ON | 是 | 指定点的Tag。要修改的属性必须在这个Tag内。 | ON player |
| 是 | 指定要修改或插入的点ID。 | "player100" | |
| SET | 是 | 指定如何修改属性值。 | SET age = age +1 |
| WHEN | 否 | 指定过滤条件。 | WHEN name == "Tim" |
| YIELD | 否 | 指定语句的输出格式。 | YIELD name AS Name |
插入不存在的点:
如果点不存在,无论 when 子句的条件是否满足,都会插入点,同时执行 set 子句,因此新插入的点的属性值取决于:
-
SET子句。
-
属性是否有默认值。
示例如下:
// 查看三个点是否存在,结果“Empty set”表示顶点不存在。
nebula> FETCH PROP ON * "player666", "player667", "player668";
+-----------+
| vertices_ |
+-----------+
+-----------+
Empty set
nebula> UPSERT VERTEX ON player "player666"
SET age = 30
WHEN name == "Joe"
YIELD name AS Name, age AS Age;
+----------+----------+
| Name | Age |
+----------+----------+
| __NULL__ | 30 |
+----------+----------+
nebula> UPSERT VERTEX ON player "player666"
SET age = 31
WHEN name == "Joe"
YIELD name AS Name, age AS Age;
+----------+-----+
| Name | Age |
+----------+-----+
| __NULL__ | 30 |
+----------+-----+
nebula> UPSERT VERTEX ON player "player667"
SET age = 31
YIELD name AS Name, age AS Age;
+----------+-----+
| Name | Age |
+----------+-----+
| __NULL__ | 31 |
+----------+-----+
nebula> UPSERT VERTEX ON player "player668"
SET name = "Amber", age = age + 1
YIELD name AS Name, age AS Age;
+---------+----------+
| Name | Age |
+---------+----------+
| "Amber" | __NULL__ |
+---------+----------+
上面最后一个示例中,因为age没有默认值,插入点时,age默认值为NULL,执行age = age + 1后仍为NULL。如果age有默认值,则age = age + 1可以正常执行,例如:
nebula> CREATE TAG IF NOT EXISTS player_with_default(name string, age int DEFAULT 20);
Execution succeeded
nebula> UPSERT VERTEX ON player_with_default "player101"
SET age = age + 1
YIELD name AS Name, age AS Age;
+----------+-----+
| Name | Age |
+----------+-----+
| __NULL__ | 21 |
+----------+-----+
修改存在的点:
如果点存在,且满足WHEN子句的条件,就会修改点的属性值。
nebula> FETCH PROP ON player "player101";
+-----------------------------------------------------+
| vertices_ |
+-----------------------------------------------------+
| ("player101" :player{age: 42, name: "Tony Parker"}) |
+-----------------------------------------------------+
nebula> UPSERT VERTEX ON player "player101"
SET age = age + 2
WHEN name == "Tony Parker"
YIELD name AS Name, age AS Age;
+---------------+-----+
| Name | Age |
+---------------+-----+
| "Tony Parker" | 44 |
+---------------+-----+
如果点存在,但是不满足WHEN子句的条件,修改不会生效。
nebula> FETCH PROP ON player "player101";
+-----------------------------------------------------+
| vertices_ |
+-----------------------------------------------------+
| ("player101" :player{age: 44, name: "Tony Parker"}) |
+-----------------------------------------------------+
nebula> UPSERT VERTEX ON player "player101"
SET age = age + 2
WHEN name == "Someone else"
YIELD name AS Name, age AS Age;
+---------------+-----+
| Name | Age |
+---------------+-----+
| "Tony Parker" | 44 |
+---------------+-----+
7.5 边语句
7.5.1 插入边
INSERT EDGE语句可以在Nebula Graph实例的指定图空间中插入一条或多条边。边是有方向的,从起始点(src_vid)到目的点(dst_vid)。
INSERT EDGE的执行方式为覆盖式插入。如果已有Edge type、起点、终点、rank都相同的边,则覆盖原边。
语法:
INSERT EDGE [IF NOT EXISTS]( ) {VALUES | VALUE} -> [@ ] : ( ) [, -> [@ ] : ( ), ...]; ::= [ [, ] ...] ::= [ [, ] ...]
-
IF NOT EXISTS:用户可以使用IF NOT EXISTS关键字检测待插入的边是否存在,只有不存在时,才会插入。
Note
- IF NOT EXISTS 仅检测<边的类型、起始点、目的点和rank>是否存在,不会检测属性值是否重合。 - IF NOT EXISTS 会先读取一次数据是否存在,因此对性能会有明显影响。
-
:边关联的Edge type,只能指定一个Edge type。Edge type必须提前创建,详情请参见CREATE EDGE。 -
:需要设置的属性名称列表。 -
src_vid:起始点ID,表示边的起点。
-
dst_vid:目的点ID,表示边的终点。
-
rank:可选项。边的rank值。默认值为0。rank值可以用来区分Edge type、起始点、目的点都相同的边。
openCypher中没有rank的概念。
-
:根据prop_name_list填写属性值。如果属性值和Edge type中的数据类型不匹配,会返回错误。如果没有填写属性值,而Edge type中对应的属性设置为NOT NULL,也会返回错误。详情请参见CREATE EDGE。
示例:
# 插入不包含属性的边
CREATE EDGE IF NOT EXISTS e1();
INSERT EDGE e1() VALUES "10"->"11":();
# 插入rank为1的边
INSERT EDGE e1() VALUES "10" -> "11"@1:();
#插入有属性的边
CREATE EDGE IF NOT EXISTS e2 (name string,age int);
INSERT EDGE e2 (name , age ) VALUES "11" -> "13":("n1",1)
#一次性插入2条边
INSERT EDGE e2 (name , age ) VALUES "12"->"13":("n1",1),"13"->"14":("n2",2)
一条边可以多次插入属性值,以最后一次为准。
# 多次插入属性值。
nebula> INSERT EDGE e2 (name, age) VALUES "11"->"13":("n1", 12);
nebula> INSERT EDGE e2 (name, age) VALUES "11"->"13":("n1", 13);
nebula> INSERT EDGE e2 (name, age) VALUES "11"->"13":("n1", 14);
nebula> FETCH PROP ON e2 "11"->"13";
+-------------------------------------------+
| edges_ |
+-------------------------------------------+
| [:e2 "11"->"13" @0 {age: 14, name: "n1"}] |
+-------------------------------------------+
使用IF NOT EXISTS插入已存在的边时,不会进行修改。
# 插入边。
nebula> INSERT EDGE e2 (name, age) VALUES "14"->"15"@1:("n1", 12);
# 使用IF NOT EXISTS修改边,因为边已存在,不会进行修改。
nebula> INSERT EDGE IF NOT EXISTS e2 (name, age) VALUES "14"->"15"@1:("n2", 13);
nebula> FETCH PROP ON e2 "14"->"15"@1;
+-------------------------------------------+
| edges_ |
+-------------------------------------------+
| [:e2 "14"->"15" @1 {age: 12, name: "n1"}] |
+-------------------------------------------+
note:
- Nebula Graph 2.6.1 允许存在悬挂边(Dangling edge)。因此可以在起点或者终点存在前,先写边;此时就可以通过
._src或 ._dst获取到(尚未写入的)点VID(不建议这样使用)。 - 目前还不能保证操作的原子性,如果失败请重试,否则会发生部分写入。此时读取该数据的行为是未定义的。
- 并发写入同一条边会报edge conflict错误,可稍后重试。
- 边的INSERT速度大约是点的INSERT速度一半。原因是INSERT边会对应storaged的两个INSERT,INSERT点对应storaged的一个INSERT。
DELETE EDGE语句可以删除边。一次可以删除一条或多条边。用户可以结合管道符一起使用,详情请参见 管道符。
如果需要删除一个点的所有出边,请删除这个点。详情请参见 DELETE VERTEX。
note:目前还不能保证操作的原子性,如果发生故障请重试。
语法:
DELETE EDGE-> [@ ] [, -> [@ ] ...]
示例:
DELETE EDGE serve "player100" -> "team204"@0;
# 结合管道符,删除符合条件的边。 GO FROM "player100" OVER follow WHEN dst(edge) == "team204" YIELD src(edge) AS src,dst(edge) AS dst,rank(edge) AS rank | DELETe EDGE follow $-.src->$-.dst @ $-.rank;7.5.3 修改边
UPDATE EDGE语句可以修改边上 Edge type 的属性。
Nebula Graph 支持 CAS(compare and set)操作。
语法:
UPDATE EDGE ON-> [@ ] SET [WHEN ] [YIELD
| 参数 | 是否必须 | 说明 | 示例 |
|---|---|---|---|
| ON | 是 | 指定 Edge type。要修改的属性必须在这个 Edge type 内。 | ON serve |
| 是 | 指定边的起始点 ID。 | "player100" | |
| 是 | 指定边的目的点 ID。 | "team204" | |
| 否 | 指定边的 rank 值。 | 10 | |
| SET | 是 | 指定如何修改属性值。 | SET start_year = start_year +1 |
| WHEN | 否 | 指定过滤条件。如果 | WHEN end_year < 2010 |
| YIELD | 否 | 指定语句的输出格式。 | YIELD start_year AS Start_Year |
示例:
# 用GO语句查看边的属性值。 GO FROM "player100" OVER serve YIELD propertier(edge).start_year,properties(edge).end_year; +------------------+----------------+ | serve.start_year | serve.end_year | +------------------+----------------+ | 1997 | 2016 | +------------------+----------------+ # 修改属性 start_year 的值,并返回 end_year 和新的 start_year UPDATe EDGE ON serve "player100" -> "team204"@0 SET start_year = start_year + 1 WHEN end_yeay > 2010 YIELD start_year,end_year7.5.4 存在修改,不存在创建 EDGE
UPSERT EDGE语句结合UPDATE和INSERT,如果边存在,会更新边的属性;如果边不存在,会插入新的边。
UPSERT EDGE性能远低于INSERT,因为UPSERT是一组分片级别的读取、修改、写入操作。
语法:
UPSERT EDGE ON-> [@rank] SET [WHEN ] [YIELD ]
| 参数 | 是否必须 | 说明 | 示例 |
|---|---|---|---|
| ON | 是 | 指定 Edge type。要修改的属性必须在这个 Edge type 内。 | ON serve |
| 是 | 指定边的起始点 ID。 | "player100" | |
| 是 | 指定边的目的点 ID。 | "team204" | |
| 否 | 指定边的 rank 值。 | 10 | |
| SET | 是 | 指定如何修改属性值。 | SET start_year = start_year +1 |
| WHEN | 否 | 指定过滤条件。 | WHEN end_year < 2010 |
| YIELD | 否 | 指定语句的输出格式。 | YIELD start_year AS Start_Year |
插入不存在的边
如果边不存在,无论WHEN子句的条件是否满足,都会插入边,同时执行SET子句,因此新插入的边的属性值取决于:
-
SET子句。
-
属性是否有默认值。
例如:
-
要插入的边包含基于 Edge typeserve的属性start_year和end_year。
-
SET子句指定end_year = 2021。
不同情况下的属性值如下表。
| 是否满足WHEN子句条件 | 属性是否有默认值 | start_year属性值 | end_year属性值 |
|---|---|---|---|
| 是 | 是 | 默认值 | 2021 |
| 是 | 否 | NULL | 2021 |
| 否 | 是 | 默认值 | 2021 |
| 否 | 否 | NULL | 2021 |
示例如下:
# 查看如下三个点是否有 serve 类型的出边,结果 "Empty set"表示没有 serve 类型的出边 GO FROM "player666","player667","player668" OVER serve YIELD properties(edge).start_year,properties(edge).end_year # 修改 UPSET EDGE on serve "player666" -> "team200"@0 SET end_year = 2021 WHEN end_year == 2010 YIELD start_year,end_year UPSERT EDGE on serve "player666" -> "team200"@0 SET end_year = 2022 WHEN end_year == 2010 YIELD start_year, end_year; UPSERT EDGE on serve "player668" -> "team200"@0 SET start_year = 2000, end_year = end_year + 1 YIELD start_year, end_year;
上面最后一个示例中,因为end_year没有默认值,插入边时,end_year默认值为NULL,执行end_year = end_year + 1后仍为NULL。如果end_year有默认值,则end_year = end_year + 1可以正常执行,例如:
nebula> CREATE EDGE IF NOT EXISTS serve_with_default(start_year int, end_year int DEFAULT 2010);
Execution succeeded
nebula> UPSERT EDGE on serve_with_default
"player668" -> "team200"
SET end_year = end_year + 1
YIELD start_year, end_year;
修改存在的边:
如果边存在,且满足WHEN子句的条件,就会修改边的属性值。
nebula> MATCH (v:player{name:"Ben Simmons"})-[e:serve]-(v2)
RETURN e;
+-----------------------------------------------------------------------+
| e |
+-----------------------------------------------------------------------+
| [:serve "player149"->"team219" @0 {end_year: 2019, start_year: 2016}] |
+-----------------------------------------------------------------------+
nebula> UPSERT EDGE on serve
"player149" -> "team219"
SET end_year = end_year + 1
WHEN start_year == 2016
YIELD start_year, end_year;
+------------+----------+
| start_year | end_year |
+------------+----------+
| 2016 | 2020 |
+------------+----------+
如果边存在,但是不满足WHEN子句的条件,修改不会生效。
nebula> MATCH (v:player{name:"Ben Simmons"})-[e:serve]-(v2)
RETURN e;
+-----------------------------------------------------------------------+
| e |
+-----------------------------------------------------------------------+
| [:serve "player149"->"team219" @0 {end_year: 2020, start_year: 2016}] |
+-----------------------------------------------------------------------+
nebula> UPSERT EDGE on serve
"player149" -> "team219"
SET end_year = end_year + 1
WHEN start_year != 2016
YIELD start_year, end_year;
+------------+----------+
| start_year | end_year |
+------------+----------+
| 2016 | 2020 |
+------------+----------+
7.6 索引(index)
7.6.1 创建index
索引的概念和使用限制都较为复杂。索引配合LOOKUP和MATCH语句使用。
CREATE INDEX语句用于对 Tag、EdgeType 或其属性创建原生索引。通常分别称为“Tag 索引”、“Edge type 索引”和“属性索引”。
-
Tag 索引和 Edge type 索引应用于和 Tag、Edge type 自身相关的查询,例如用LOOKUP查找有 Tag player的所有点。
-
“属性索引”应用于基于属性的查询,例如基于属性age找到age == 19的所有的点。
备注:
- 不要任意在生产环境中使用索引,除非很清楚使用索引对业务的影响。索引会导致写性能下降 90%甚至更多。
- 索引并不用于查询加速。只用于:根据属性定位到点或边,或者统计点边数量。
- 长索引会降低 Storage 服务的扫描性能,以及占用更多内存。建议将索引长度设置为和要被索引的最长字符串相同。索引长度最长为 255,超过部分会被截断。
语法:
CREATE {TAG | EDGE} INDEX [IF NOT EXISTS] ON { | } ([]) [COMMENT = ''];
| 参数 | 说明 |
|---|---|
| TAG | EDGE | 指定要创建的索引类型。 |
| IF NOT EXISTS | 检测待创建的索引是否存在,只有不存在时,才会创建索引。 |
| 索引名。索引名在一个图空间中必须是唯一的。推荐的命名方式为i_tagName_propName。索引名称由大小写英文字母、数字或下划线组成,区分大写小,且不可使用关键字和保留字。 | |
| 指定索引关联的 Tag 或 Edge 名称。 | |
| 为变长字符串属性创建索引时,必须用prop_name(length)指定索引长度;为 Tag 或 Edge type 本身创建索引时,忽略 | |
| COMMENT | 索引的描述。最大为 256 字节。默认无描述。 |
示例:
- 创建 tag 索引
CREATE TAG INDEX player_index on player();
-
创建edge索引
CREATE EDGE INDEX follow_index on follow();
-
创建单属性的索引
CREATE TAG INDEX IF EXISTS player_index_0 on player(name(10));
-
创建复合属性索引
CREATE TAG INDEX IF NOT EXISTS player_index_1 on player(name(10) , age)
备注:
不支持跨 Tag 或者 Edge type创建复合索引
创建索引之后需要重建索引使其生效
7.6.2 显示index 语法:
SHOW {TAG | EDGE} INDEXES;
SHOW INDEXES语句可以列出当前图空间内的所有 Tag 和 Edge type(包括属性)的索引。
7.6.3 显示创建index语句语法:
SHOW CREATE {TAG | EDGE} INDEX ;
SHOW CREATE INDEX展示创建 Tag 或者 Edge type 时使用的 nGQL 语句,其中包含索引的详细信息,例如其关联的属性。
7.6.4 显示index的信息语法:
DESCRIBE {TAG | EDGE} INDEX ;
DESCRIBE INDEX语句可以查看指定索引的信息,包括索引的属性名称(Field)和数据类型(Type)。
7.6.5 重建index语法:
REBUILD {TAG | EDGE} INDEX [];
::=
[index_name [, index_name] ...]
-
可以一次重建多个索引,索引名称之间用英文逗号(,)分隔。如果没有指定索引名称,将会重建所有索引。
-
重建完成后,用户可以使用命令SHOW {TAG | EDGE} INDEX STATUS检查索引是否重建完成。详情请参见 SHOW INDEX STATUS。
语法:
SHOW {TAG | EDGE} INDEX STATUS;
索引的状态包括:
- QUEUE:队列中
- RUNNING:执行中
- FINISHED:已完成
- FAILED:失败
- STOPPED:停止
- INVALID:失效
语法:
DROp {TAG | EDGE} INDEX [IF EXISTS] ;
8 查询nGQL
8.1 MATCH
前提条件:
请确保MATCH语句有至少一个索引可用,或者其中指定了 VID。如果需要创建索引,但是已经有相关的点、边或属性,用户必须在创建索引后重建索引,索引才能生效。
匹配 Tag
match (n:player) return n
匹配点的属性
match (n:player{name:"Tim"}) return n
或者
match (n:player) where n.name == 'Tim' return n
匹配连接的点
用户可以使用--符号表示两个方向的边,并匹配这些边连接的点
MATCH (v:player{name:"Tim Duncan"})--(v2) RETURN v2.name AS Name
8.2 LOOKUP
8.3 GO
语法:
GO [[TO] STEPS ] FROM OVER [{REVERSELY | BIDIRECT}] [ WHERe ] [YIELD [DISTINCT] ] [{SAMPLE | LIMIT }] [| GROUP BY {col_name | expr | position} YIELD ] [| ORDER BY [{ASC | DESC}]] [| LIMIT [ ,] ]; ::= [, ...] ::= edge_type [, edge_type ...] | * ::= [AS ] [, [AS ] ...]
M TO N STEPS:遍历M~N跳的边。如果M为0,输出结果和M为1相同,即GO 0 TO 2和GO 1 TO 2是相同的。M TO N STEPS:遍历M~N跳的边。如果M为0,输出结果和M为1相同,即GO 0 TO 2和GO 1 TO 2是相同的。
REVERSELY | BIDIRECT:默认情况下检索的是
WHERe
YIELD [DISTINCT]
SAMPLE
LIMIT
GROUP BY:根据指定属性的值将输出分组。分组后需要再次使用YIELD定义需要返回的输出。
ORDER BY:指定输出结果的排序规则。
LIMIT [
示例:
返回 player102 所属队伍
GO FROM "player102" over serve;
返回距离 player102 两跳的朋友
GO 2 STEPS FROM "player102" OVER follow;
添加过滤条件
GO FROM "player100","player102" over serve
WHERe serve.start_year > 1995
YIELD DISTINCT properties($$).name AS team_name,properties(edge).start_year AS start_year,properties($^).name AS player_name;
遍历多个 Edge type。属性没有值时,会显示 UNKNOWN_PROP
GO FROM "player100" OVER follow ,serve
YIELD properties(edge).degree,properties(edge).start_year;
返回 player100 入方向的邻居点
GO FROM "player100" OVER follow REVERSELY
YIELD src(edge) AS destination;
# 该 MATCH 查询与上一个 GO 查询具有相同的语义。
nebula> MATCH (v)<-[e:follow]- (v2) WHERe id(v) == 'player100'
RETURN id(v2) AS destination;
# 该 MATCH 查询与上一个 GO 查询具有相同的语义。
nebula> MATCH (v)<-[e:follow]- (v2) WHERe id(v) == 'player100'
RETURN id(v2) AS destination;
# 该 MATCH 查询与上一个 GO 查询具有相同的语义。
nebula> MATCH (v)<-[e:follow]- (v2)-[e2:serve]->(v3)
WHERe id(v) == 'player100'
RETURN v2.name AS FriendOf, v3.name AS Team;
# 查询 player100 1~2 跳内的朋友。
nebula> GO 1 TO 2 STEPS FROM "player100" OVER follow
YIELD dst(edge) AS destination;
# 该 MATCH 查询与上一个 GO 查询具有相同的语义。
nebula> MATCH (v) -[e:follow*1..2]->(v2)
WHERe id(v) == "player100"
RETURN id(v2) AS destination;
# 根据年龄分组。
nebula> GO 2 STEPS FROM "player100" OVER follow
YIELD src(edge) AS src, dst(edge) AS dst, properties($$).age AS age
| GROUP BY $-.dst
YIELD $-.dst AS dst, collect_set($-.src) AS src, collect($-.age) AS age;
# 分组并限制输出结果的行数。
nebula> $a = GO FROM "player100" OVER follow YIELD src(edge) AS src, dst(edge) AS dst;
GO 2 STEPS FROM $a.dst OVER follow
YIELD $a.src AS src, $a.dst, src(edge), dst(edge)
| ORDER BY $-.src | OFFSET 1 LIMIT 2;
# 在多个边上通过 IS NOT EMPTY 进行判断。
nebula> GO FROM "player100" OVER follow WHERe $$.player.name IS NOT EMPTY YIELD dst(edge);
8.4 FETCH
参考官网
8.5 UNWIN参考官网
8.6 SHOW参考官网



