图数据库nebula graph小结

nebula graph操作手册

1. 摘抄网址

官网: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/<release_version>/nebula-graph-<release_version>.el7.x86_64.rpm

//Centos 8
https://oss-cdn.nebula-graph.com.cn/package/<release_version>/nebula-graph-<release_version>.el8.x86_64.rpm

//Ubuntu 1604
https://oss-cdn.nebula-graph.com.cn/package/<release_version>/nebula-graph-<release_version>.ubuntu1604.amd64.deb

//Ubuntu 1804
https://oss-cdn.nebula-graph.com.cn/package/<release_version>/nebula-graph-<release_version>.ubuntu1804.amd64.deb

//Ubuntu 2004
https://oss-cdn.nebula-graph.com.cn/package/<release_version>/nebula-graph-<release_version>.ubuntu2004.amd64.deb

例如要下载适用于Centos 7.52.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 18042.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.deb

3.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

  1. 使用如下命令查看 Nebula Graph 版本。

    $ dpkg -l | grep "nebula"
    

    返回类似如下结果。

    ii  nebula-graph  2.6.1  amd64     Nebula Package built using CMake
    
  2. 使用如下命令卸载 Nebula Graph。

    sudo dpkg -r <nebula_version>
    

    例如:

    sudo dpkg -r nebula-graph
    
  3. 删除安装目录。

4. 启动Nebula Graph服务

​ Nebula Graph使用脚本nebula.service管理服务,包括启动、停止、重启、中止和查看。

nebula.service的默认路径是/usr/local/nebula/scripts,如果修改过安装路径,请使用实际路径。

语法:

$ sudo /usr/local/nebula/scripts/nebula.service
[-v] [-c <config_file_path>]
<start|stop|restart|kill|status>
<metad|graphd|storaged|all>
参数说明
-v显示详细调试信息。
-c指定配置文件路径,默认路径为/usr/local/nebula/etc/
start启动服务。
stop停止服务。
restart重启服务。
kill中止服务。
status查看服务状态。
metad管理Meta服务。
graphd管理Graph服务。
storaged管理Storage服务。
all管理所有服务。

4.1 启动所有服务

sudo /usr/local/nebula/scripts/nebula.service start all 

4.2 停止所有服务

sudo /usr/local/nebula/scripts/nebula.service stop all

4.3 查看所有服务

sudo /usr/local/nebula/scripts/nebula.service status all

5. 连接Nebula Graph服务

5.1 前提条件

  • Nebula Graph服务已启动。

  • 运行Nebula Console的机器和运行Nebula Graph的服务器网络互通。

5.2 操作步骤

  1. Nebula Console下载页面,确认需要的版本,单击Assets

  2. Assets区域找到机器运行所需的二进制文件,下载文件到机器上

    下载: nebula-console-linux-amd64-v2.6.1

  3. (可选)为方便使用,重命名文件为nebula-console

  4. 在运行Nebula Console的机器上执行如下命令,为用户授予nebula-console文件的执行权限。

  5. 在命令行界面中,切换工作目录至nebula-console文件所在目录。

  6. 执行如下命令连接Nebula Graph。

     ./nebula-console -addr <ip> -port <port> -u <username> -p <password>  [-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 Studio

Nebula 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

  • 确保在安装开始前,以下端口处于未被使用状态。

端口号说明
7001Studio提供的web服务
8080Nebula-http-gateway,Client的HTTP服务
6.1.2 安装
  1. 根据需要下载 tar 包,建议选择最新版本。

    安装包Studio 版本
    nebula-graph-studio-3.1.0.x86_64.tar.gz3.1.0
  2. 使用 tar -xvf 解压 tar 包。

    tar -xvf nebula-graph-studio-3.1.0.x86_64.tar.gz
    
6.1.3 部署
  1. 部署 nebula-http-gateway 并启动。

    $ cd nebula-http-gateway
    $ nohup ./nebula-httpd &
    

    查看nebula-httpd服务是否启动成功: ps -ef | grep nebula-httpd

    如果没有启动成功则页面会显示: 请求错误:504 Gateway Timeout
    在这里插入图片描述

  2. 部署 nebula-graph-studio 并启动。

    $ cd nebula-graph-studio
    $ npm run start
    
  3. 启动成功后,在浏览器地址栏输入 http://ip address:7001

​ 如果在浏览器窗口中能看到以下登录界面,表示已经成功部署并启动 Studio。
在这里插入图片描述

6.2 停止服务

​ 用户可以采用 kill pid 的方式来关停服务:

kill $(lsof -t -i :8080) # stop nebula-http-gateway
cd nebula-graph-studio
npm run stop # stop nebula-graph-studio

6.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
	密码: 123456

6.4 部署多机集群

6.4.1 部署方案

准备5台用于部署集群的机器

机器名称IP 地址graphd 进程数量storaged 进程数量metad 进程数量
A192.168.10.111111
B192.168.10.112111
C192.168.10.113111
D192.168.10.11411-
E192.168.10.11511-
6.4.2 手动部署流程
  1. 安装nebula Graph

    在集群的每台服务器上都安装nebula Graph,安装后暂不需要启动服务。

  2. 修改配置文件

    修改每个服务器上的nebula Graph配置文件。

    Nebula Graph的所有配置文件均位于安装目录的etc目录内,包括nebula-graphd.confnebula-metad.confnebula-storaged.conf,用户可以只修改所需服务的配置文件。各个机器需要修改的配置文件如下。

    机器名称待修改配置文件
    Anebula-graphd.confnebula-storaged.confnebula-metad.conf
    Bnebula-graphd.confnebula-storaged.confnebula-metad.conf
    Cnebula-graphd.confnebula-storaged.confnebula-metad.conf
    Dnebula-graphd.confnebula-storaged.conf
    Enebula-graphd.confnebula-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
    
6.4.3 启动集群

依次启动各个服务器上的对应进程。

机器名称待启动的进程
Agraphd、storaged、metad
Bgraphd、storaged、metad
Cgraphd、storaged、metad
Dgraphd、storaged
Egraphd、storaged

启动 Nebula Graph 进程的命令如下:

sudo /usr/local/nebula/scripts/nebula.service start <metad|graphd|storaged>
6.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] <graph_space_name> (
    [partition_num = <partition_number>,]
    [replica_factor = <replica_number>,]
    vid_type = {FIXED_STRING(<N>) | INT[64]}
    )
    [ON <group_name>]
    [COMMENT = '<comment>'];
参数说明
IF NOT EXISTS检测待创建的图空间是否存在,只有不存在时,才会创建图空间。仅检测图空间的名称,不会检测具体属性。
<graph_space_name>在Nebula Graph实例中唯一标识一个图空间。图空间名称由大小写英文字母、数字或下划线组成,区分大写小,且不可使用关键字和保留字
partition_num指定图空间的分片数量。建议设置为5倍的集群硬盘数量。例如集群中有3个硬盘,建议设置15个分片。默认值为100。
replica_factor指定每个分片的副本数量。建议在生产环境中设置为3,在测试环境中设置为1。由于需要基于多数表决,副本数量必须是奇数。默认值为1。
vid_type必选参数。指定点ID的数据类型。可选值为FIXED_STRING(<N>)INT64INT等同于INT64FIXED_STRING(<N>)表示数据类型为字符串,最大长度为N,超出长度会报错;INT64表示数据类型为整数。
ON <group_name>指定图空间所属的Group。详情请参见Group&Zone
COMMENT图空间的描述。最大为256字节。默认无描述。

备注 :

  1. 如果将副本数设置为1,用户将无法使用BALANCE命令为Nebula Graph的存储服务平衡负载或扩容。
  2. 在Nebula Graph 1.x中,VID的类型只能为INT64,不支持字符型;在Nebula Graph 2.x中, VID的类型支持INT64FIXED_STRING(<N>)。请在创建图空间时指定VID类型,使用INSERT语句时也需要保持一致,否则会报错VID类型不匹配Wrong vertex id type: 1001
  3. 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 使用
USE <graph_space_name>;
例如:use test1;
7.1.3 显示所有space
SHOW SPACES;
7.1.4 显示space的详细信息
DESC[RIBE] SPACE <graph_space_name>;
例如: desc space test1
7.1.5 删除space
DROP SPACE [IF EXISTS] <graph_space_name>;
例如: 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] <tag_name>
    (
      <prop_name> <data_type> [NULL | NOT NULL] [DEFAULT <default_value>] [COMMENT '<comment>']
      [{, <prop_name> <data_type> [NULL | NOT NULL] [DEFAULT <default_value>] [COMMENT '<comment>']} ...] 
    )
    [TTL_DURATION = <ttl_duration>]
    [TTL_COL = <prop_name>]
    [COMMENT = '<comment>'];
参数说明
IF NOT EXISTS检测待创建的Tag是否存在,只有不存在时,才会创建Tag。仅检测Tag的名称,不会检测具体属性。
<tag_name>每个图空间内的Tag必须是唯一的。Tag名称设置后无法修改。Tag名称由大小写英文字母、数字或下划线组成,区分大写小,且不可使用关键字和保留字
<prop_name>属性名称。每个Tag中的属性名称必须唯一。属性的命名规则与Tag相同。
<data_type>属性的数据类型,目前支持数值布尔字符串以及日期与时间
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] <tag_name>;
  • 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 <tag_name>
    <alter_definition> [[, alter_definition] ...]
    [ttl_definition [, ttl_definition] ... ]
    [COMMENT = '<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语句中使用多个ADDDROPCHANGE子句,子句之间用英文逗号(,)分隔。

示例:

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 <tag_name>;

DESCRIBE可以缩写为DESC

示例:

 DESCRIBE TAG player;
7.2.6 删除tag

DELETE TAG语句可以删除指定点上的指定Tag。

点可以有一个或多个Tag。

  • 如果某个点只有一个Tag,删除这个点上的Tag后,用户就无法访问这个点,下次Compaction操作时会删除该点,但点上的边仍然存在。

  • 如果某个点有多个Tag,删除其中一个Tag,仍然可以访问这个点,但是无法访问这个点上已删除Tag所定义的所有属性。

前提条件:

登录的用户必须拥有对应权限才能执行DELETE TAG语句。详情请参见内置角色权限

语法:

DELETE TAG <tag_name_list> FROM <VID>;
  • 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 <index_name_list>;语句重建索引。

7.3 边: edge

7.3.1 创建

语法:

创建Edge type前,需要先用USE语句指定工作空间。

CREATE EDGE [IF NOT EXISTS] <edge_type_name>
    (
      <prop_name> <data_type> [NULL | NOT NULL] [DEFAULT <default_value>] [COMMENT '<comment>']
      [{, <prop_name> <data_type> [NULL | NOT NULL] [DEFAULT <default_value>] [COMMENT '<comment>']} ...] 
    )
    [TTL_DURATION = <ttl_duration>]
    [TTL_COL = <prop_name>]
    [COMMENT = '<comment>'];
参数说明
IF NOT EXISTS检测待创建的Edge type是否存在,只有不存在时,才会创建Edge type。仅检测Edge type的名称,不会检测具体属性。
<edge_type_name>每个图空间内的Edge type必须是唯一的。Edge type名称设置后无法修改。Edge type名称由大小写英文字母、数字或下划线组成,区分大写小,且不可使用关键字和保留字
<prop_name>属性名称。每个Edge type中的属性名称必须唯一。属性的命名规则与Edge type相同。
<data_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] <edge_type_name>
  • 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 <edge_type_name>

	<alter_definition [, alter_definition]  ... ]

	 [ttl_definition [, ttl_definition] ... ]    [COMMENT = '<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
  • edge_type_name:指定要修改的Edge type名称。一次只能修改一个Edge type。请确保要修改的Edge type在当前工作空间中存在,否则会报错。

  • 可以在一个ALTER EDGE语句中使用多个ADDDROPCHANGE子句,子句之间用英文逗号(,)分隔。

示例:

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 <edge_type_name>

DESCRIBE可以缩写为DESC

7.4 点语句

7.4.1 插入点 INSERT VERTEX

INSERT VERTEX语句可以在Nebula Graph实例的指定图空间中插入一个或多个点。

语法:

INSERT VERTEX [IF NOT EXISTS] <tag_name> (<prop_name_list>) [, <tag_name> (<prop_name_list>), ...]
     {VALUES | VALUE} VID: (<prop_value_list>[, <prop_value_list>])

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)。
    • 相同VIDTAG的情况下,如果没有使用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  <vid>   [ ,<vid> .... ]

示例:

	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 ON <tag_name> <vid>
SET <update_prop>
[WHEN <condition>]
[YIELD <output>]
参数是否必须说明示例
ON <tag_name>指定点的Tag。要修改的属性必须在这个Tag内。ON player
<vid>指定要修改的点ID。"player100"
SET <update_prop>指定如何修改属性值。SET age = age +1
WHEN <condition>指定过滤条件。如果<condition>结果为falseSET子句不会生效。WHEN name == "Tim"
YIELD <output>指定语句的输出格式。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语句结合UPDATEINSERT,如果点存在,会修改点的属性值;如果点不存在,会插入新的点。

note: UPSERT VERTEX一次只能修改一个Tag。

UPSERT VERTEX性能远低于INSERT,因为UPSERT是一组分片级别的读取、修改、写入操作。

note: 禁止在高并发写操作的情况下使用UPSERT语句,请使用UPDATEINSERT代替。

语法:

UPSERT VERTEX ON <tag> <vid>
SET <update_prop>
[WHEN <condition>]
[YIELD <output>]
参数是否必须说明示例
ON <tag>指定点的Tag。要修改的属性必须在这个Tag内。ON player
<vid>指定要修改或插入的点ID。"player100"
SET <update_prop>指定如何修改属性值。SET age = age +1
WHEN <condition>指定过滤条件。WHEN name == "Tim"
YIELD <output>指定语句的输出格式。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] <edge_type> ( <prop_name_list> ) {VALUES | VALUE}
<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> ] ...]
  • IF NOT EXISTS:用户可以使用IF NOT EXISTS关键字检测待插入的边是否存在,只有不存在时,才会插入。

    Note

    - IF NOT EXISTS 仅检测<边的类型、起始点、目的点和rank>是否存在,不会检测属性值是否重合。 - IF NOT EXISTS 会先读取一次数据是否存在,因此对性能会有明显影响。

  • <edge_type>:边关联的Edge type,只能指定一个Edge type。Edge type必须提前创建,详情请参见CREATE EDGE

  • <prop_name_list>:需要设置的属性名称列表。

  • src_vid:起始点ID,表示边的起点。

  • dst_vid:目的点ID,表示边的终点。

  • rank:可选项。边的rank值。默认值为0。rank值可以用来区分Edge type、起始点、目的点都相同的边。

    openCypher中没有rank的概念。

  • <prop_value_list>:根据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)。因此可以在起点或者终点存在前,先写边;此时就可以通过 <edgetype>._src<edgetype>._dst获取到(尚未写入的)点VID(不建议这样使用)。
  • 目前还不能保证操作的原子性,如果失败请重试,否则会发生部分写入。此时读取该数据的行为是未定义的。
  • 并发写入同一条边会报edge conflict错误,可稍后重试。
  • 边的INSERT速度大约是点的INSERT速度一半。原因是INSERT边会对应storaged的两个INSERT,INSERT点对应storaged的一个INSERT。
7.5.2 删除边

DELETE EDGE语句可以删除边。一次可以删除一条或多条边。用户可以结合管道符一起使用,详情请参见 管道符

如果需要删除一个点的所有出边,请删除这个点。详情请参见 DELETE VERTEX

note:目前还不能保证操作的原子性,如果发生故障请重试。

语法:

DELETE EDGE <edge_type> <src_vid> -> <dst_vid>[@<rank>] [, <src_vid> -> <dst_vid>[@<rank>] ...]

示例:

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 <edge_type>
<src_vid> -> <dst_vid> [@<rank>]
SET <update_prop>
[WHEN <condition>]
[YIELD <output>]
参数是否必须说明示例
ON <edge_type>指定 Edge type。要修改的属性必须在这个 Edge type 内。ON serve
<src_vid>指定边的起始点 ID。"player100"
<dst_vid>指定边的目的点 ID。"team204"
<rank>指定边的 rank 值。10
SET <update_prop>指定如何修改属性值。SET start_year = start_year +1
WHEN <condition>指定过滤条件。如果<condition>结果为falseSET子句不会生效。WHEN end_year < 2010
YIELD <output>指定语句的输出格式。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_year
7.5.4 存在修改,不存在创建 EDGE

UPSERT EDGE语句结合UPDATEINSERT,如果边存在,会更新边的属性;如果边不存在,会插入新的边。

UPSERT EDGE性能远低于INSERT,因为UPSERT是一组分片级别的读取、修改、写入操作。

语法:

UPSERT EDGE ON <edge_type>
<src_vid> -> <dst_vid> [@rank]
SET <update_prop>
[WHEN <condition>]
[YIELD <properties>]
参数是否必须说明示例
ON <edge_type>指定 Edge type。要修改的属性必须在这个 Edge type 内。ON serve
<src_vid>指定边的起始点 ID。"player100"
<dst_vid>指定边的目的点 ID。"team204"
<rank>指定边的 rank 值。10
SET <update_prop>指定如何修改属性值。SET start_year = start_year +1
WHEN <condition>指定过滤条件。WHEN end_year < 2010
YIELD <output>指定语句的输出格式。YIELD start_year AS Start_Year

插入不存在的边

如果边不存在,无论WHEN子句的条件是否满足,都会插入边,同时执行SET子句,因此新插入的边的属性值取决于:

  • SET子句。

  • 属性是否有默认值。

例如:

  • 要插入的边包含基于 Edge typeserve的属性start_yearend_year

  • SET子句指定end_year = 2021

不同情况下的属性值如下表。

是否满足WHEN子句条件属性是否有默认值start_year属性值end_year属性值
默认值2021
NULL2021
默认值2021
NULL2021

示例如下:

# 查看如下三个点是否有 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

​ 索引的概念和使用限制都较为复杂。索引配合LOOKUPMATCH语句使用。

CREATE INDEX语句用于对 Tag、EdgeType 或其属性创建原生索引。通常分别称为“Tag 索引”、“Edge type 索引”和“属性索引”。

  • Tag 索引和 Edge type 索引应用于和 Tag、Edge type 自身相关的查询,例如用LOOKUP查找有 Tag player的所有点。

  • “属性索引”应用于基于属性的查询,例如基于属性age找到age == 19的所有的点。

备注:

  1. 不要任意在生产环境中使用索引,除非很清楚使用索引对业务的影响。索引会导致写性能下降 90%甚至更多。
  2. 索引并不用于查询加速。只用于:根据属性定位到点或边,或者统计点边数量。
  3. 长索引会降低 Storage 服务的扫描性能,以及占用更多内存。建议将索引长度设置为和要被索引的最长字符串相同。索引长度最长为 255,超过部分会被截断。

语法:

CREATE {TAG | EDGE} INDEX [IF NOT EXISTS] <index_name> ON {<tag_name> | <edge_name>} ([<prop_name_list>]) [COMMENT = '<comment>'];
参数说明
TAG \| EDGE指定要创建的索引类型。
IF NOT EXISTS检测待创建的索引是否存在,只有不存在时,才会创建索引。
<index_name>索引名。索引名在一个图空间中必须是唯一的。推荐的命名方式为i_tagName_propName。索引名称由大小写英文字母、数字或下划线组成,区分大写小,且不可使用关键字和保留字
<tag_name> \| <edge_name>指定索引关联的 Tag 或 Edge 名称。
<prop_name_list>变长字符串属性创建索引时,必须用prop_name(length)指定索引长度;为 Tag 或 Edge type 本身创建索引时,忽略<prop_name_list>
COMMENT索引的描述。最大为 256 字节。默认无描述。

示例:

  1. 创建 tag 索引
	CREATE TAG INDEX player_index on player();
  1. 创建edge索引

    CREATE EDGE INDEX follow_index on follow();
    
  2. 创建单属性的索引

    CREATE TAG INDEX IF EXISTS player_index_0 on player(name(10));
    
  3. 创建复合属性索引

    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 <index_name>;

SHOW CREATE INDEX展示创建 Tag 或者 Edge type 时使用的 nGQL 语句,其中包含索引的详细信息,例如其关联的属性。

7.6.4 显示index的信息

语法:

DESCRIBE {TAG | EDGE} INDEX <index_name>;

DESCRIBE INDEX语句可以查看指定索引的信息,包括索引的属性名称(Field)和数据类型(Type)。

7.6.5 重建index

语法:

REBUILD {TAG | EDGE} INDEX [<index_name_list>];

<index_name_list>::=
    [index_name [, index_name] ...]
  • 可以一次重建多个索引,索引名称之间用英文逗号(,)分隔。如果没有指定索引名称,将会重建所有索引。

  • 重建完成后,用户可以使用命令SHOW {TAG | EDGE} INDEX STATUS检查索引是否重建完成。详情请参见 SHOW INDEX STATUS

7.6.6 查询index状态

语法:

SHOW {TAG | EDGE} INDEX STATUS;

索引的状态包括:

  • QUEUE:队列中
  • RUNNING:执行中
  • FINISHED:已完成
  • FAILED:失败
  • STOPPED:停止
  • INVALID:失效
7.6.7 删除index

语法:

DROP {TAG | EDGE} INDEX [IF EXISTS] <index_name>;

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 [[<M> TO] <N> STEPS ] FROM <vertex_list>
OVER <edge_type_list> [{REVERSELY | BIDIRECT}]
[ WHERE <conditions> ]
[YIELD [DISTINCT] <return_list>]
[{SAMPLE <sample_list> | LIMIT <limit_list>}]
[| GROUP BY {col_name | expr | position} YIELD <col_name>]
[| ORDER BY <expression> [{ASC | DESC}]]
[| LIMIT [<offset>,] <number_rows>];

<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:指定跳数。如果没有指定跳数,默认值N1。如果N0,Nebula Graph 不会检索任何边。GO语句采用的路径类型是walk,即遍历时点和边可以重复。

M TO N STEPS:遍历M~N跳的边。如果M0,输出结果和M1相同,即GO 0 TO 2GO 1 TO 2是相同的。M TO N STEPS:遍历M~N跳的边。如果M0,输出结果和M1相同,即GO 0 TO 2GO 1 TO 2是相同的。

<vertex_list>:用逗号分隔的点 ID 列表,或特殊的引用符$-.id

<edge_type_list>:遍历的 Edge type 列表。

REVERSELY | BIDIRECT:默认情况下检索的是<vertex_list>的出边(正向),REVERSELY表示反向,即检索入边;BIDIRECT 为双向,即检索正向和反向,通过返回 <edge_type>._type 字段判断方向,其正数为正向,负数为反向。

WHERE <conditions>:指定遍历的过滤条件。用户可以在起始点、目的点和边使用WHERE子句,还可以结合ANDORNOTXOR一起使用。详情参见 WHERE

YIELD [DISTINCT] <return_list>:定义需要返回的输出。<return_list>建议使用 Schea 函数,当前支持src(edge)dst(edge)type(edge)rank(edge)properties(edge)id(vertex)properties(vertex),暂不支持嵌套函数。如果没有指定,默认返回目的点 ID。

SAMPLE <sample_list>:用于在结果集中取样。

LIMIT <limit_list>:用于在遍历过程中逐步限制输出数量。

GROUP BY:根据指定属性的值将输出分组。分组后需要再次使用YIELD定义需要返回的输出。

ORDER BY:指定输出结果的排序规则。

LIMIT [<offset>,] <number_rows>]:限制输出结果的行数。

示例:

返回 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

参考官网

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值