人之初,性本鸽。

大家好,我叫储惠龙(实名上网),你可以叫我小龙人,00后一枚。目前从事后端开发工作。

今天给大家带来一个简单的为NebulaGraph提供GraphQL查询支持的DEMO,为什么是简单的,因为本来想完成更多工作再给大家介绍的,但是上个月太忙加上下个月更忙,但是我又很想白嫖一下Nebula官方的奖品,所以就赶紧端上来了。

Untitled

先上项目地址:https://github.com/Dragonchu/NebulaGraphQL

先简单介绍一下GraphQL,https://graphql.cn/ 详细的信息官方介绍的都很清晰。说一下我的理解,GraphQL并不是对标Cypher这种查询语言,而是对标REST的一种API设计风格。所以严格意义上,不是说使用GraphQL查询图数据库,而是使用一种GraphQL风格的API查询图数据库,或者说是将Cypher封装了一样,这个本质工作和大家做应用开发时,基于Nebula写一些通过的REST接口是一样的。

举个例子(本文的测试数据集使用的官方的basketballplayer数据集https://docs.nebula-graph.io/2.0/basketballplayer-2.X.ngql),如果我想根据科比的名字得到科比的全部信息,可能会使用下面这样的Ngql语句

LOOKUP ON player WHERE player.name == "Kobe Bryant" YIELD id(vertex) as vertexId | FETCH PROP ON player $-.vertexId YIELD properties(vertex);

虽然说Ngql已经很方便阅读了,但是如果让一个完全0基础的萌新来看也是看不懂的,并且这个语句的返回值是不明确的,至少没有办法从查询看到结果。返回值的解析一直也是很多人的痛苦。

那来看看使用GraphQL查询同一场景会是什么情况。

查询语句会是

{
	players(name:"Kobe Bryant"){
		name
		age
	}
}

返回结果是

{
	players=[{name=Kobe Bryant, age=40}]
}

看看这优雅的查询和返回结果,想必我不多说,大家也都看得懂。这真的是

Untitled

这其实就是官方对GraphQL的总结:

描述你的数据、请求你所要的数据、得到可预测的结果。

上述的查询在NebulaGraphQL中已经实现了,同时还支持通过VertexID查询数据(好吧,我也就实现了这两种)。

在项目中使用NebulaGraphQL也非常非常的简单,因为NebulaGraphQL本身只想做一个简单的工具库,未来如果想直接集成到MVC框架可能会再起一个NebulaGraphQL-spring之类的项目(画大饼中……)。所以NebulaGraphQL的使用和Nebula-Java是几乎完全一致的。

//创建一个config
GraphqlSessionPoolConfig graphqlSessionPoolConfig = new GraphqlSessionPoolConfig(
                Lists.newArrayList(graphdAddress),
                Lists.newArrayList(metadAddress),
                spaceName, username, password);
//创建一个连接池
GraphqlSessionPool pool = new GraphqlSessionPool(graphqlSessionPoolConfig);
//执行语句
ExecutionResult executionResult = pool.execute("{players(age:32){name\nage}}");
//获取结果
System.out.println(executionResult.getData().toString());

其实GraphSessionPool内部就是使用的Nebula-Java的SessionPool。所有配置都和使用官方提供的连接池一致,唯一的区别是需要额外提供metad的连接地址。这是因为NebulaGraphQL是通过Metad来自动构建schema的,NebulaGraphQL会在创建连接池时自动创建schema。

NebulaGraphQL主要是基于GraphQL-Java实现的,其实使用GraphQL-Java,大家可以根据自己的项目定义自己的GraphQL的schema,不过NebulaGraphQL想尽可能的提供一些通用功能,并且一定是根据Nebula的schema自动构建的。

当然,NebulaGraphQL的目标不只是简单将Ngql映射到GraphQL这么简单,因为GraphQL除了查询简单这个很明朗的特点,还可以更轻松的支持权限管理,以及通过DataLoader机制在应用层实现一层缓存,不过我这边目前也没有研究的很透彻,如果有大佬愿意加入一起实现那就最好不过了。

为了方便大家贡献(主要是我懒),NebulaGraphQL的开发以及完成了一部分的容器化了,将代码库克隆到本地后,本地只需要有docker,然后在仓库根目录下运行

docker-compose -f docker-compose.dev.yml up --build

就可以看到在自动跑测试了,会在本地启动Nebula集群并自动插入测试的数据,后续会继续优化这方面的流程。

NebulaGraphQL提供了更简单的查询语句,这个查询语句的构造应该是让前端直接提供的,GraphQL的优势之一就是可以让前端选择自己需要的数据从而避免“接口地狱”,可能会有人认为这相当于让前端直接访问数据库了。是的,我觉得这个理解也确实没问题,这也是有人反对GraphQL的理由,不过这里就不继续讨论了。

但是使用GraphQL有一个潜在优势,也就是可以更轻松的将图数据库和关系型数据库整合在一起。当然如果只是使用图数据库的话,那使用NebulaGraphQL至少也能方便做一些简单的数据查询与测试。

Untitled

其实对于NebulaGraphQL在实际生产中的价值目前我也没有体验过,因为纯属兴趣写着玩儿,如果大家有想法,欢迎在评论区交流。