赞
踩
一、基础概念
二、初步使用
三、整合SpringBoot使用
Nebula Graph 是一款开源的、分布式的、易扩展的原生图数据库,能够承载包含数千亿个点和数万亿条边的超大规模数据集,并且提供毫秒级查询。
图数据库:图数据库是专门存储庞大的图形网络并从中检索信息的数据库。它可以将图中的数据高效存储为点(Vertex)
和边(Edge)
,还可以将属性(Property)
附加到点和边上。
Nebula Graph 可用于各种基于图的业务场景。为节约转换各类数据到关系型数据库的时间,以及避免复杂查询,建议使用 Nebula Graph。
欺诈检测¶金融机构必须仔细研究大量的交易信息,才能检测出潜在的金融欺诈行为,并了解某个欺诈行为和设备的内在关联。这种场景可以通过图来建模,然后借助 Nebula Graph,可以很容易地检测出诈骗团伙或其他复杂诈骗行为。
实时推荐¶Nebula Graph 能够及时处理访问者产生的实时信息,并且精准推送文章、视频、产品和服务。
知识图谱¶自然语言可以转化为知识图谱,存储在 Nebula Graph 中。用自然语言组织的问题可以通过智能问答系统中的语义解析器进行解析并重新组织,然后从知识图谱中检索出问题的可能答案,提供给提问人。
社交网络¶人际关系信息是典型的图数据,Nebula Graph 可以轻松处理数十亿人和数万亿人际关系的社交网络信息,并在海量并发的情况下,提供快速的好友推荐和工作岗位查询。
Nebula Graph 数据模型使用 6 种基本的数据模型:
图空间(Space):图空间用于隔离不同团队或者项目的数据。不同图空间的数据是相互隔离的,可以指定不同的存储副本数、权限、分片等。
点(Vertex):点用来保存实体对象,特点如下:点是用点标识符(VID)标识的。VID在同一图空间中唯一。VID 是一个 int64,或者 fixed_string(N)。点可以有 0 到多个 Tag(一个Tag包含一组预先指定的KV键值对)。(Nebula Graph 2.x 及以下版本中的点必须包含至少一个 Tag。)
边(Edge):边是用来连接点的,表示两个点之间的关系或行为,特点如下:
标签(Tag):Tag 由一组事先预定义的属性构成。
边类型(Edge type):Edge type 由一组事先预定义的属性构成。
属性(Property):属性是指以键值对(Key-value pair)形式表示的信息。
对比关系型数据库中的概念解释Tag、EdgeType等概念:https://www.bilibili.com/video/BV1Q5411K7Gg?zw
图论中一个非常重要的概念是路径,路径是指一个有限或无限的边序列,这些边连接着一系列点。
路径的类型分为三种:walk、trail、path。
walk:walk类型的路径由有限或无限的边序列构成。遍历时点和边可以重复。查看示例图,由于 C、D、E 构成了一个环,因此该图包含无限个路径,例如A->B->C->D->E
、A->B->C->D->E->C
、A->B->C->D->E->C->D
。
trail:trail类型的路径由有限的边序列构成。遍历时只有点可以重复,边不可以重复。柯尼斯堡七桥问题的路径类型就是trail。查看示例图,由于边不可以重复,所以该图包含有限个路径,最长路径由 5 条边组成:A->B->C->D->E->C
。又可分为两种类型cycle 和 circuit。
A->B->C->A
或C->D->E->C
.(当出现任意一个闭环)A->B->C->D->E->C->A
。path:path类型的路径由有限的边序列构成。遍历时点和边都不可以重复。由于点和边都不可以重复,所以该图包含有限个路径,最长路径由 4 条边组成:A->B->C->D->E
。
总结
在 Nebula Graph 中,一个点由点的 ID 唯一标识,即 VID 或 Vertex ID。参考:https://docs.nebula-graph.com.cn/3.1.0/1.introduction/3.vid/
1、VID 的特点
FIXED_STRING(<N>)
或INT64
;一个图空间只能选用其中一种 VID 类型。2、VID 使用建议
性能上,
直接通过 VID 找到点的语句性能最高,例如DELETE xxx WHERE id(xxx) == "player100"
,或者GO FROM "player100"
等语句。
通过属性先查找 VID,再进行图操作的性能会变差,例如LOOKUP | GO FROM $-.ids
等语句,相比前者多了一次内存或硬盘的随机读(LOOKUP)
以及一次序列化(|)
。
3、VID 生成建议,VID 的生成工作完全交给应用端,有一些通用的建议:
FIXED_STRING(<N>)
的N设置成超大,这会浪费大量内存和硬盘,也会降低性能。此时可通过 BASE64,MD5,hash 编码加拼接的方式来生成。如果用 hash 方式生成 int64 VID:在有 10 亿个点的情况下,发生 hash 冲突的概率大约是 1/10。边的数量与碰撞的概率无关。4、定义和修改 VID 与其数据类型
VID 的数据类型必须在创建图空间时定义,且一旦定义无法修改。
VID 必须在插入点时设置,且一旦设置无法修改。
5、“查询起始点”(start vid) 与全局扫描
(MATCH、GO、LOOKUP)
的执行计划,必须要通过一定方式找到查询起始点的 VID(start vid)。定位 start vid 只有两种方式:
例如 GO FROM "player100" OVER
是在语句中显式的指明 start vid 是 "player100"
;
例如 LOOKUP ON player WHERE player.name == "Tony Parker"
或者 MATCH (v:player {name:"Tony Parker"})
,是通过属性 player.name
的索引来定位到 start vid;
这部分直接看官网文档:https://docs.nebula-graph.com.cn/3.1.0/1.introduction/3.nebula-graph-architecture/2.meta-service/,分为三部分,每个服务运行在单独的进程
其中存储结构图示
因为我的服务器到期了,因此在本地windows使用docker compose来进行安装。
参考安装步骤:https://www.jianshu.com/p/1c939f86357b
docker compose安装nebula的步骤官网中文手册:https://docs.nebula-graph.com.cn/3.1.0/,https://docs.nebula-graph.com.cn/3.1.0/4.deployment-and-installation/2.compile-and-install-nebula-graph/3.deploy-nebula-graph-with-docker-compose/
1、在windows上安装docker desktop之后包含了docker compose,保证本地安装过git即可
2、使用git bush打开自定义的目录位置,然后选择指定版本clone到本地,如果克隆失败可以直接下载压缩包到本地
# clone nebula-docker-compose,失败的话可以直接代开git仓库,然后下载zip解压也可
$ git clone -b release-3.1 https://github.com/vesoft-inc/nebula-docker-compose.git
# 切换到指定目录,使用命令行工具打开
$ cd nebula-docker-compose/
# 下面这个命令失败可以多试几次,推荐使用powershell
$ docker-compose up -d
3、执行到此步就已安装完成,查看安装的Nebula相关服务,可以看到
nebula-docker-compose-310_console_1
:命令行连接工具nebula-docker-compose-310_graphd xxx _1
nebula-docker-compose-310_metad xxx _1
nebula-docker-compose-310_storaged xxx _1
4、查看服务状态和端口,想要修改的话直接修改docker-compose.yaml配置文件即可
1、使用docker exec -it nebula-docker-compose-310_console_1 /bin/sh
进入容器内部
2、通过 Nebula Console 连接 Nebula Graph。执行命令./usr/local/bin/nebula-console -u root -p renyi --address=graphd --port=9669
。默认情况下,身份验证功能是关闭的,用户可以使用 root 用户名和任意密码连接到 Nebula Graph。
3、打开登录连接密码
参考:https://docs.nebula-graph.com.cn/3.1.0/7.data-security/1.authentication/1.authentication/
4、停止服务命令:docker-compose down
首先看支持的基本数据结构类型
创建
修改,图空间一旦创建不可修改
# 模板 CREATE SPACE [IF NOT EXISTS] <graph_space_name> ( [partition_num = <partition_number>,] [replica_factor = <replica_number>,] vid_type = {FIXED_STRING(<N>) | INT64} ) [COMMENT = '<comment>']; # 创建举栗 CREATE SPACE basketballplayer( partition_num=15, replica_factor=1, vid_type=fixed_string(30) ); # 查看所有图空间 show spaces # 选中某个图空间 use xxx
创建、删除、修改Tag等操作参考官网文档:https://docs.nebula-graph.com.cn/3.1.0/3.ngql-guide/10.tag-statements/1.create-tag/
创建、删除、修改Edge Type等操作参考官网文档:https://docs.nebula-graph.com.cn/3.1.0/3.ngql-guide/11.edge-type-statements/1.create-edge/
# 创建模板汇总
CREATE
{TAG | EDGE}
[IF NOT EXISTS]
{<tag_name> | <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>'];
以创建Tag参数举栗,CREATE TAG语句可以通过指定名称创建一个 Tag。
CREATE TAG [IF NOT EXISTS] # 检测待创建的 Tag 是否存在,只有不存在时,才会创建 Tag。仅检测 Tag 的名称,不会检测具体属性。 <tag_name> # 每个图空间内的 Tag 必须是唯一的。Tag 名称设置后无法修改。 # Tag 名称以英文字母开头,支持 1~4 字节的 UTF-8 编码字符,包括英文字母(区分大小写)、数字、中文等,但是不包括除下划线外的特殊字符。使用特殊字符或保留关键字时,需要用反引号(`)包围,详情参见关键字和保留字。 ( <prop_name> # 属性名称。每个 Tag 中的属性名称必须唯一。属性的命名规则与 Tag 相同。 <data_type> # 属性的数据类型,目前支持数值、布尔、字符串以及日期与时间。 [NULL | NOT NULL] # 指定属性值是否支持为NULL。默认值为NULL。 [DEFAULT <default_value>] # 指定属性的默认值。默认值可以是一个文字值或 Nebula Graph 支持的表达式。如果插入点时没有指定某个属性的值,则使用默认值。 [COMMENT '<comment>'] # 对单个属性或 Tag 的描述说明。最大为 256 字节。默认无描述。 # 省略 [{, <prop_name> <data_type> [NULL | NOT NULL] [DEFAULT <default_value>] [COMMENT '<comment>']} ...] ) [TTL_DURATION = <ttl_duration>] [TTL_COL = <prop_name>] [COMMENT = '<comment>'];
举栗创建Tag
nebula> CREATE TAG IF NOT EXISTS player(name string, age int);
# 创建没有属性的 Tag。
nebula> CREATE TAG IF NOT EXISTS no_property();
# 创建包含默认值的 Tag。
nebula> CREATE TAG IF NOT EXISTS player_with_default(name string, age int DEFAULT 20);
# 对字段 create_time 设置 TTL 为 100 秒。
nebula> CREATE TAG IF NOT EXISTS woman(name string, age int, \
married bool, salary double, create_time timestamp) \
TTL_DURATION = 100, TTL_COL = "create_time";
举栗创建EdgeType
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";
用户可以使用INSERT语句,基于现有的 Tag 插入点,或者基于现有的 Edge type 插入边。
# 插入点模板 INSERT VERTEX # [IF NOT EXISTS] # 仅检测 VID + Tag 的值是否相同,不会检测属性值。 IF NOT EXISTS 会先读取一次数据是否存在,因此对性能会有明显影响。 [tag_props, [tag_props] ...] VALUES <vid>: ([prop_value_list]) #vid是 Vertex ID 的缩写,vid在一个图空间中是唯一的。 # 参数详情请参见:https://docs.nebula-graph.com.cn/3.1.0/3.ngql-guide/12.vertex-statements/1.insert-vertex/ # 说明 tag_props: tag_name ([prop_name_list]) prop_name_list: [prop_name [, prop_name] ...] prop_value_list: [prop_value [, prop_value] ...] # 举栗 # 1. 插入一个点player100,包含标签player以及对应的值 (root@nebula) [basketballplayer]> INSERT VERTEX player(name, age) VALUES "player100":("Tim Duncan", 42); # 2. 插入一个点player101,包含标签player以及对应的值 (root@nebula) [basketballplayer]> INSERT VERTEX player(name, age) VALUES "player101":("Tony Parker", 36); # 3. 插入一个点player102,包含标签player以及对应的值 (root@nebula) [basketballplayer]> INSERT VERTEX player(name, age) VALUES "player102":("LaMarcus Aldridge", 33); # 1. 插入两个点team203、team204,包含标签team以及对应的值 (root@nebula) [basketballplayer]> INSERT VERTEX team(name) VALUES "team203":("Trail Blazers"), "team204":("Spurs");
# 插入边模板 INSERT EDGE [IF NOT EXISTS] <edge_type> ( <prop_name_list> ) VALUES <src_vid> -> <dst_vid>[@<rank>] : ( <prop_value_list> ) [, <src_vid> -> <dst_vid>[@<rank>] : ( <prop_value_list> ), ...]; # 说明 <prop_name_list> ::= [ <prop_name> [, <prop_name> ] ...] <prop_value_list> ::= [ <prop_value> [, <prop_value> ] ...] # 举栗 # 1. 插入一条 点player101->点player100 类型为follow的边,权值为95 (root@nebula) [basketballplayer]> INSERT EDGE follow(degree) VALUES "player101" -> "player100":(95); # 2. 插入一条 player101->player102 类型为follow的边,权值为90 (root@nebula) [basketballplayer]> INSERT EDGE follow(degree) VALUES "player101" -> "player102":(90); # 3. 插入一条 player102->player100 类型为follow的边,权值为75 (root@nebula) [basketballplayer]> INSERT EDGE follow(degree) VALUES "player102" -> "player100":(75); (root@nebula) [basketballplayer]> INSERT EDGE serve(start_year, end_year) VALUES "player101" -> "team204":(1999, 2018), # 插入一条 点player101->点team204 类型为server 的边,属性值为(1999, 2018) "player102" -> "team203":(2006, 2015); # 插入一条 点player102->点team203 类型为server 的边,属性值为(2006, 2015)
支持下列四种语句
GO
[[<M> TO] <N> STEPS ]
FROM
<vertex_list>
OVER
<edge_type_list> [{REVERSELY | BIDIRECT}]
[ WHERE <conditions> ]
YIELD
[DISTINCT] <return_list>
[{ SAMPLE <sample_list> | <limit_by_list_clause> }]
[| GROUP BY {<col_name> | expression> | <position>} YIELD <col_name>]
[| ORDER BY <expression> [{ASC | DESC}]]
[| LIMIT [<offset>,] <number_rows>];
举栗1:从 VID 为player101的球员开始,沿着边follow找到连接的球员: GO FROM "player101" OVER follow YIELD id($$);
举栗2:从 VID 为player101的球员开始,沿着边follow查找年龄大于或等于 35 岁的球员,并返回他们的姓名和年龄,同时重命名对应的列:
GO FROM "player101"
OVER follow
WHERE properties($$).age >= 35
YIELD
properties($$).name AS Teammate,
properties($$).age AS Age;
# YIELD 指定该查询需要返回的值或结果。
# $$ 表示边的终点。
# \ 表示换行继续输入。
举栗3:从 VID 为player101的球员开始,沿着边follow查找连接的球员,然后检索这些球员的球队。为了合并这两个查询请求,可以使用管道符或临时变量。
GO FROM "player101" OVER follow YIELD dst(edge) AS id | GO FROM $-.id OVER serve YIELD properties($$).name AS Team, properties($^).name AS Player; +-----------------+---------------------+ | Team | Player | +-----------------+---------------------+ | "Spurs" | "Tim Duncan" | | "Trail Blazers" | "LaMarcus Aldridge" | | "Spurs" | "LaMarcus Aldridge" | | "Spurs" | "Manu Ginobili" | +-----------------+---------------------+ # $^ 表示边的起点。 # | 组合多个查询的管道符,将前一个查询的结果集用于后一个查询。 # $- 表示管道符前面的查询输出的结果集。
举栗4:使用临时变量
# 当复合语句作为一个整体提交给服务器时,其中的临时变量会在语句结束时被释放。 $var = GO FROM "player101" OVER follow YIELD dst(edge) AS id; GO FROM $var.id OVER serve YIELD properties($$).name AS Team, properties($^).name AS Player; +-----------------+---------------------+ | Team | Player | +-----------------+---------------------+ | "Spurs" | "Tim Duncan" | | "Trail Blazers" | "LaMarcus Aldridge" | | "Spurs" | "LaMarcus Aldridge" | | "Spurs" | "Manu Ginobili" | +-----------------+---------------------+
# 查询 Tag 属性
FETCH PROP ON
{<tag_name>[, tag_name ...] | *}
<vid> [, vid ...]
YIELD
<return_list> [AS <alias>];
#查询边属性
FETCH PROP ON
<edge_type> <src_vid> -> <dst_vid>[@<rank>]
[, <src_vid> -> <dst_vid> ...]
YIELD
<output>;
举栗
# 查询 VID 为player100的球员的属性。
FETCH PROP ON
player "player100"
YIELD properties(vertex);
+-------------------------------+
| properties(VERTEX) |
+-------------------------------+
| {age: 42, name: "Tim Duncan"} |
+-------------------------------+
LOOKUP ON {<vertex_tag> | <edge_type>}
[WHERE <expression> [AND <expression> ...]]
YIELD <return_list> [AS <alias>];
<return_list>
<prop_name> [AS <col_alias>] [, <prop_name> [AS <prop_alias>] ...];
基于索引的LOOKUP举栗,确保LOOKUP有一个索引可用。如果没有,请先创建索引。
# 找到 Tag 为player的点的信息,它的name属性值为Tony Parker。 // 为 name 属性创建索引 player_index_1。 nebula> CREATE TAG INDEX IF NOT EXISTS player_index_1 ON player(name(20)); // 重建索引确保能对已存在数据生效。 REBUILD TAG INDEX player_index_1 +------------+ | New Job Id | +------------+ | 31 | +------------+ // 使用 LOOKUP 语句检索点的属性。 LOOKUP ON player WHERE player.name == "Tony Parker" YIELD properties(vertex).name AS name, properties(vertex).age AS age; +---------------+-----+ | name | age | +---------------+-----+ | "Tony Parker" | 36 | +---------------+-----+
基于索引的MATCH举栗,确保MATCH有一个索引可用。如果没有,请先创建索引。
MATCH <pattern> [<clause_1>]
RETURN <output> [<clause_2>];
举栗
# 找到 Tag 为player的点的信息,它的name属性值为Tony Parker。
// 使用 MATCH 语句检索点的属性。
MATCH (v:player{name:"Tony Parker"})
RETURN v;
+-----------------------------------------------------+
| v |
+-----------------------------------------------------+
| ("player101" :player{age: 36, name: "Tony Parker"}) |
+-----------------------------------------------------+
其他更多命令参考官网文档:https://docs.nebula-graph.com.cn/3.1.0/2.quick-start/6.cheatsheet-for-ngql-command/
参考官网文档:https://docs.nebula-graph.com.cn/3.1.0/nebula-studio/deploy-connect/st-ug-deploy/,下载比较慢的可以为docker配置国内镜像源参考:https://blog.csdn.net/seantdj/article/details/106372955
在命令行工具中按以下步骤依次运行命令,部署并启动 Docker 版 Studio,这里我们用 Nebula Graph 版本为 3.1.0 的进行演示:
下载 Studio 的部署配置文件。安装包 适用 Nebula 版本3.1.0 nebula-graph-studio-3.3.1.tar.gz
创建nebula-graph-studio-3.3.1目录,并将安装包解压至目录中。mkdir nebula-graph-studio-3.3.1 && tar -zxvf nebula-graph-studio-3.3.1.tar.gz -C nebula-graph-studio-3.3.1
解压后进入 nebula-graph-studio-3.3.1 目录。cd nebula-graph-studio-3.3.1
拉取 Studio 的 Docker 镜像。docker-compose pull
构建并启动 Studio 服务。其中,-d 表示在后台运行服务容器。docker-compose up -d
当屏幕返回以下信息时,表示 Docker 版 Studio 已经成功启动。启动成功后,在浏览器地址栏输入 http://<ip address>:7001
。需要找到本机的IPv4地址,可以使用ipconfig或者设置查看。连接参考官方文档:https://docs.nebula-graph.com.cn/3.1.0/nebula-studio/deploy-connect/st-ug-connect/
完整整合代码放到了github:https://github.com/sichaolong/spring-demo/tree/main/springboot-nebula-graph-demo
参考官方文档:https://docs.nebula-graph.com.cn/3.1.0/14.client/1.nebula-client/
Java客户端使用文档:https://docs.nebula-graph.com.cn/3.1.0/14.client/4.nebula-java-client/
新建一个SpringBoot工程,注意不要使用aliyun的仓库,它的仓库还没有新的nebula的客户端依赖,pom文件添加响应的依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.7</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>henu.soft</groupId> <artifactId>study_nebula_graph_demo</artifactId> <version>0.0.1</version> <name>study_nebula_graph_demo</name> <description>SpringBoot整合nebula图数据库</description> <properties> <java.version>11</java.version> </properties> <dependencies> <!-- nebula客户端--> <dependency> <groupId>com.vesoft</groupId> <artifactId>client</artifactId> <version>3.0.0</version> </dependency> <!-- fastjson--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.78</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> </project>
参考官方给的demo代码,编写测试代码
package henu.soft.study_nebula_graph_demo; import com.vesoft.nebula.client.graph.NebulaPoolConfig; import com.vesoft.nebula.client.graph.data.HostAddress; import com.vesoft.nebula.client.graph.exception.AuthFailedException; import com.vesoft.nebula.client.graph.exception.ClientServerIncompatibleException; import com.vesoft.nebula.client.graph.exception.IOErrorException; import com.vesoft.nebula.client.graph.exception.NotValidConnectionException; import com.vesoft.nebula.client.graph.net.NebulaPool; import com.vesoft.nebula.client.graph.net.Session; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import java.net.UnknownHostException; import java.util.Arrays; import java.util.List; @SpringBootTest @Slf4j public class NebulaDemoTest { @Test void testNebulaConnection(){ log.info("开始连接nebula数据库...."); NebulaPool pool = new NebulaPool(); Session session; try { NebulaPoolConfig nebulaPoolConfig = new NebulaPoolConfig(); nebulaPoolConfig.setMaxConnSize(100); List<HostAddress> addresses = Arrays.asList(new HostAddress("127.0.0.1", 9669)); Boolean initResult = pool.init(addresses, nebulaPoolConfig); if (!initResult) { log.error("pool init failed."); return; } session = pool.getSession("root", "nebula", false); boolean pingRes = session.ping(); log.info("ping 结果为 :{}",pingRes); } catch (UnknownHostException e) { e.printStackTrace(); } catch (NotValidConnectionException e) { e.printStackTrace(); } catch (AuthFailedException e) { e.printStackTrace(); } catch (ClientServerIncompatibleException e) { e.printStackTrace(); } catch (IOErrorException e) { e.printStackTrace(); } } }
打印结果为
使用之前创建的basketballplayer
图空间
# 1. 查找包含player标签的点
match (v:player) return v limit 10
# 2. 查找包含team标签的点
match (v:team) return v limit 10
# 3. 查找所有点的边关系
match ()<-[e]-() return e limit 10
完整代码已经放在github上:https://github.com/sichaolong/spring-demo/tree/main/springboot-nebula-graph-demo
package henu.soft.study_nebula_graph_demo; import com.vesoft.nebula.client.graph.exception.IOErrorException; import henu.soft.study_nebula_graph_demo.pojo.Info; import henu.soft.study_nebula_graph_demo.utils.NebulaTemplate; import henu.soft.study_nebula_graph_demo.vo.NebulaResult; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import javax.annotation.Resource; @SpringBootTest @Slf4j public class NebulaTemplateTest { // NebulaTemplate 是为了方便获取session执行封装的工具类。仓库地址:https://github.com/sichaolong/study-nebula_graph_demo @Resource NebulaTemplate nebulaTemplate; @Test void addJSON() throws IOErrorException { log.info("开始像图空间添加一个点...[ v: {},name: {},age: {} ]","player103","xiaosi","21"); String sql = "INSERT VERTEX player(name, age) VALUES \n" + "\t\"player103\":(\"xiaosi\", 21);"; NebulaResult nebulaResult = nebulaTemplate.executeObject(sql); log.info("添加结果:{}",nebulaResult.toString()); } }
命令行查询数据库,发现成功添加
(root@nebula) [basketballplayer]> match (v:player) return id(v) as id,v.player.name as name,v.player.age as age limit 10;
+-------------+---------------------+-----+
| id | name | age |
+-------------+---------------------+-----+
| "player101" | "Tony Parker" | 36 |
| "player102" | "LaMarcus Aldridge" | 33 |
| "player103" | "xiaosi" | 21 |
| "player100" | "Tim Duncan" | 42 |
+-------------+---------------------+-----+
查询包含player标签的所有点,其中player是自定义的pojo,包含id、name、age属性, NebulaResult<T>
是封装的返回查询结果类,返回的数据在data中
@Test void findJson2() throws IOErrorException { // lookup 至少需要一个索引 // String sql = "lookup on player yield id(vertex) AS id,properties(vertex).name AS name,properties(vertex).age AS age;"; String sql = "match (v:player) return id(v) as id,v.player.name as name,v.player.age as age limit 10;"; NebulaResult<player> playerInfoNebulaResult = nebulaTemplate.queryObject(sql, player.class); log.info("查询包含player标签的所有点:{}" ,playerInfoNebulaResult.toString()); } // 输出 /* NebulaResult( code=0, message=null, data=[ player(id=player101, name=Tony Parker, age=36), player(id=player102, name=LaMarcus Aldridge, age=33), player(id=player103, name=xiaosi, age=21), player(id=player100, name=Tim Duncan, age=42) ] ) */
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。