首页 > 数据库 >当 GraphQL 遇上图数据库,便有了更方便查询数据的方式

当 GraphQL 遇上图数据库,便有了更方便查询数据的方式

时间:2023-06-14 18:56:20浏览次数:56  
标签:name 数据库 NebulaGraphQL player GraphQL 查询 NebulaGraph 遇上

人之初,性本鸽。

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

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

pic1|284x177

体验 NebulaGraphQL

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

GraphQL 是什么

先简单介绍一下 GraphQL,https://graphql.cn/ 详细的信息官方介绍得都很清晰。说一下我的理解,GraphQL 并不是对标 Cypher 这种查询语言,而是对标 REST 的一种 API 设计风格

所以,严格意义上,不是说使用 GraphQL 查询图数据库,而是使用一种 GraphQL 风格的 API 查询图数据库,或者说是将 Cypher 封装了一样。这个本质工作和大家做应用开发时,基于 NebulaGraph 写一些通过的 REST 接口是一样的。

API 查询示例

本文的测试数据集使用的 NebulaGraph 官方的 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}]
}

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

pic2|220x230

其实上面说了那么多,就是官方对 GraphQL 的总结:描述你的数据、请求你所要的数据、得到可预测的结果

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

NebulaGraphQL 简单入门

NebulaGraphQL 是一个 Java 库,旨在应用层提供使用 GraphQL 语法查询 NebulaGraph 图数据库中数据的能力。

在项目中使用 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 的实现

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

在创建 GraphqlSessionPool 时,NebulaGraphQL 通过连接 NebulaGraphQL 的 metad 将 NebulaGraph 中的元数据信息构造成 GraphQL 的 Schema 信息。这一部分是关键难题。目前,我仅仅做了如下的变换:

  1. 对于 NebulaGraph 中所有的 Tag,都会构造一个对应的 GraphQL 的可查询对象。
  2. 每一个 Tag 都会有一个同名的根据 ID 获取信息的查询。举例来说,对于 player 这个 tag,会生成一个查询 player,这个查询的参数是 vertexID,会根据 vertexID 获取到信息。
  3. 每一个 Tag 都会有一个在名称后加 -s 的查询。举例来说,对于 player 这个 tag,会生成一个查询 players,这个查询的参数是任意的属性。如果 player 上有 age,name,country 这些属性,在查询参数中可以传入这三种属性的任意组合,NebulaGraphQL 查询时会将这些参数进行“与” AND 语义的构造,再获取相关顶点。对于用户没有指定的参数,默认为 null(这是一个已知的问题,如果目的就是查 null 会有问题)。

测试数据集上自动生成的 GraphQL 的 Schema 示例:

type Query {
 player(
 "Vertex ID"
 ID: ID
): player
players(age: Int = null, name: String = null): [player]!
team(
"Vertex ID"
ID: ID
): team
 teams(name: String = null): [team]!
}
type player {
age: Int
name: String
}
type team {
name: String
}

简单讲解一下,Query 是 GraphQL 的查询入口,其中的 player, players, team, teams 都是自动生成的查询,可以当作查询语句。

player 是根据 VertexID 查询并返回一个 player,player 后面没有 ! 标识符,说明可能查询结果为空。players 查询有两个参数,对应着 player 这个 tag 的两个属性 age 和 name,这两个参数的类型都从 NebulaGraph 中的数据类型映射到了 GraphQL 的数据类型,默认值都为 null,返回值是一个列表。列表后的 !,说明一定返回一个列表,但是其中的 player 后没有 ! 标识符,指的是可能返回一个空列表。

使用 players 查询,参数可以指定 age 或者 name,或者 age 和 name 一起指定。

下面的 player 和 team 两个 type 就表示了这两个对象有什么属性,可以在查询时指定返回的属性,NebulaGraphQL 在返回结果时就只会提供查询需要的属性。

每一个 GraphQL 的查询会有一个绑定的 DataFetcher 对象,该对象中实现的就是如何将 GraphQL 语法映射成 nGQL 语句,并执行插叙返回结果。而返回结果会映射到自定义对象上,这里使用了我另一个小工具NebulaResultBoot 将执行结果映射到自定的对象上后,我们就可以在未来实现应用层的缓存,当然这里也有一个潜在的问题:每一次查询都要求获取到每一个点边的所有属性,这部分未来需要考虑优化。

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

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

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

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

小结

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

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

pic3|225x225

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

标签:name,数据库,NebulaGraphQL,player,GraphQL,查询,NebulaGraph,遇上
From: https://www.cnblogs.com/nebulagraph/p/17481111.html

相关文章

  • 【后端面经-数据库】MySQL的事务隔离级别简介
    目录0.事务的概念1.三类问题2.事务隔离级别3.操作指令4.总结5.参考博文0.事务的概念事务指的是一连串的集中操作指令,一个事务的执行必须执行完所有的动作才能算作执行结束。事务具有四个特点,简记作ACID:A-Atomicity:原子性,事务的执行必须保证所有的动作都执行完毕;C-Co......
  • 如何使用MySQL存储过程简化数据库操作
    在数据库管理领域,MySQL已成为最受欢迎和最可靠的选择之一。MySQL不仅提供了强大的数据存储能力,还提供了一种称为“过程”的强大功能,使开发人员能够简化复杂的数据库操作。在本教程中,我们将深入研究MySQL过程的概念并探索它们的好处。然后,我将提供有关如何有效使用它们的分步......
  • mysql数据库数据同步几种通用方法?
    MySQL数据库数据同步的几种通用方法包括以下几个方面:一、基于主从同步主从同步是MySQL数据库最为常见和基本的同步方式,即其中一台MySQL服务器作为主服务器(Master),另外一台或多台MySQL服务器作为从服务器(Slave)。主服务器处理写入数据的请求,并将数据的变化复制到从服务器,以......
  • 在FreeSWITCH中使用Lua脚本来将电话记录存储到MySQL数据库中
    在FreeSWITCH中使用Lua脚本来将电话记录存储到MySQL数据库中,需要做以下几个步骤:安装MySQL客户端库首先需要通过包管理器(如apt-get或yum)安装MySQL客户端库,以便FreeSWITCH能够与MySQL数据库进行通信。例如,在Ubuntu系统中,可以运行以下命令进行安装:sudoapt-getinstalllibmysq......
  • jexcel_删除行并同步数据库
    写在*.aspx中1//删除行OK2varmyDeleteRow=function(){3varDBID=document.getElementById("my_textbox").value;4//vartempConfirm=confirm("DBID为:"+DBID);//弹出确认框5vartempConfirm=confir......
  • jexcel_增加行并同步数据库
    写在*.aspx中1//增加行OK2varaddRow=function(){3varfieldName="type";//字段名4varmodifyValue="请输入";//值5//vartempConfirm=confirm("modifyValue:"+modifyValue+"......
  • MySQL 表信息查询,便于补数据库结构设计文档
    MySQL表信息查询,便于补数据库结构设计文档selectc.table_name表名,t.TABLE_COMMENT表说明,c.COLUMN_NAME列名,c.COLUMN......
  • 查询配置数据库 视图 响应时长优化问题
    问题: 主数据库为oracle,配置数据库SqlServer,有个子页面查询SqlServer数据库视图,需要二十多秒才给响应处理方案:把查询分页数据的SQL 和查询分页计数的SQL异步处理原代码:page=iMpckService.getsympzkcSqlserver(params);//查询SQLserver数据库total=iMp......
  • 2023.6.13 05.数据库索引操作
    05.数据库索引操作1.索引概述2.索引分类3.索引环境4.索引创建5.索引测试6.索引管理 1.索引概述索引就好⽐⼀本书的⽬录,它会让你更快的找到内容,显然⽬录(索引)并不是越多越好,假如这本书1000⻚,有500⻚也是⽬录,它当然效率低,⽬录是要占纸张的,⽽索引是要占磁盘空间的。 ......
  • 2023.6.13 06.数据库触发器
    06.数据库触发器1、什么叫触发器:当满⾜⼀定的条件以后,它会触发⼀个动作的执⾏,trigger触发器是⼀种特殊类型的存储过程,它是在特定的表上⾃动执⾏的代码。当特定的事件发⽣时,MySQL触发器会被⾃动激活。这些事件可能包括INSERT、UPDATE或DELETE操作,以及对特定列的更改。2......