人之初,性本鸽。
【资料图】
大家好,我叫储惠龙(实名上网),你可以叫我小龙人,00 后一枚。目前从事后端开发工作。
今天给大家带来一个简单的为 NebulaGraph 提供 GraphQL 查询支持的 DEMO,为什么是简单的,因为本来想完成更多工作再给大家介绍的,但是上个月太忙加上下个月更忙,但是我又很想白嫖一下 Nebula 官方的奖品,所以就赶紧端上来了。
先上项目地址:https://github.com/Dragonchu/NebulaGraphQL
先简单介绍一下 GraphQL,https://graphql.cn/ 详细的信息官方介绍得都很清晰。说一下我的理解,GraphQL 并不是对标 Cypher 这种查询语言,而是对标 REST 的一种 API 设计风格。
所以,严格意义上,不是说使用 GraphQL 查询图数据库,而是使用一种 GraphQL 风格的 API 查询图数据库,或者说是将 Cypher 封装了一样。这个本质工作和大家做应用开发时,基于 NebulaGraph 写一些通过的 REST 接口是一样的。
本文的测试数据集使用的 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"){nameage}}
返回结果是:
{players=[{name=Kobe Bryant, age=40}]}
看看这优雅的查询和返回结果,想必我不多说,大家也都看得懂。这真的是
其实上面说了那么多,就是官方对 GraphQL 的总结:描述你的数据、请求你所要的数据、得到可预测的结果。
上述的查询在 NebulaGraphQL 中已经实现了,同时还支持通过 VertexID 查询数据(好吧,我也就实现了这两种)。
NebulaGraphQL 是一个 Java 库,旨在应用层提供使用 GraphQL 语法查询 NebulaGraph 图数据库中数据的能力。
在项目中使用 NebulaGraphQL 非常简单,因为 NebulaGraphQL 本身只想做一个简单的工具库,未来如果想直接集成到 MVC 框架可能会再起一个 NebulaGraphQL-Spring 之类的项目(画大饼中……)。所以 NebulaGraphQL 的使用和 nebula-java 是几乎完全一致的。
使用示例:
//创建一个configGraphqlSessionPoolConfig 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 想尽可能地提供一些通用功能,并且一定是根据 NebulaGraph 的 Schema 自动构建的。
在创建 GraphqlSessionPool 时,NebulaGraphQL 通过连接 NebulaGraphQL 的 metad 将 NebulaGraph 中的元数据信息构造成 GraphQL 的 Schema 信息。这一部分是关键难题。目前,我仅仅做了如下的变换:
-s
的查询。举例来说,对于 player 这个 tag,会生成一个查询 players,这个查询的参数是任意的属性。如果 player 上有 age,name,country 这些属性,在查询参数中可以传入这三种属性的任意组合,NebulaGraphQL 查询时会将这些参数进行“与” AND
语义的构造,再获取相关顶点。对于用户没有指定的参数,默认为 null(这是一个已知的问题,如果目的就是查 null 会有问题)。测试数据集上自动生成的 GraphQL 的 Schema 示例:
type Query { player( "Vertex ID" ID: ID): playerplayers(age: Int = null, name: String = null): [player]!team("Vertex ID"ID: ID): team teams(name: String = null): [team]!}type player {age: Intname: 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 至少也能方便做一些简单的数据查询与测试。
对于 NebulaGraphQL 在实际生产中的价值目前我也没有体验过,因为纯属兴趣写着玩儿,如果大家有想法,欢迎在评论区交流。
标签:
主场0-0战平成都蓉城还可以,其他比赛无论面对中超强队还是保级对手,
连日来,生态环境耀州分局联合耀州城管、交警、交通运输等执法部门加强
1、0 8的计数单位是0 10 800。本文到此分享完毕,希望对大家有所帮助。
新海南客户端、南海网6月14日消息(记者刘子榕)近日,经三亚市政府同
Netflix是填补电影历史空白的好方法。无论是您错过的最新上映影片还是
每年的6月下旬,我们就要迎来传统节日——端午节,今年的端午节有三天
国家医保局飞行检查48家定点医疗机构追回医保基金7 2亿元---新华社北京
6月14日消息,天眼查App显示,饿了么关联公司拉扎斯网络科技(上海)有
2023年降成本工作通知出台,小规模纳税人免征增值税,小型微利企业减半
1个月24份罚单!监管狠抓券商研报质控进行时,罚单,证监会,中证协,分析
最新规划方案发布!弘诚体育场将“大
最新规划方案发布!弘诚体育场将“大变身”,新建全民健身馆、田径场等
省高院民三庭赴岳阳自贸片区调研|天
6月13日,省高院民三庭赴岳阳自贸片区调研。红网时刻岳阳6月14日讯(记
【全球新要闻】让更多人会用、敢用“
□钱夙伟6月12日上午,在中国红十字基金会的支持下,厦门市红十字会携
退休人员发放过节费真的有吗?杭州地
每年的6月下旬,我们就要迎来传统节日——端午节,今年的端午节有三天
前沿热点:滴滴快送上线200余城 UU
同城即时配送也迎来首个聚合类平台——滴滴快送。6月13日,滴滴出行平
纯白花嫁绝美!《战舰少女R》昆西五
UnknownModel幽蓦文化旗下来自手游《战舰少女R》昆西的五月花的约定1 7
退出印度之后,越南制造也有麻烦,苹
日前媒体报道指苹果在越南的代工厂面临麻烦,由于越南缺乏足够的电力供
什么叫小肠火小肠火的症状_小肠火的
1、小肠火是尿路感染的俗称,常见急性泌尿性膀胱炎。2、主要症状是膀胱
visa卡卡号的第一位数字是什么?visa
visa卡卡号的第一位数字是什么?visa是以数字4开头,卡号通常是16位数,具体的visa银行卡号可以直接在持卡人自己的卡片表面进行查看。国际标准
加元符号和美元符号的区别在哪里?加
加元符号和美元符号的区别在哪里?加元符号也是$表示,美元符号也是$表示,实际上两者是有差别的: 美元的货币符号是US$,两竖$特指美元,一竖$
广东省鹤山市组织优秀教职工疗休养_
广东省鹤山市组织优秀教职工疗休养中工网讯6月10日,广东江门鹤山市202
思想会客厅|点旺城市“烟火气” 释
思想会客厅|点旺城市“烟火气”释放发展新活力,
4000095555是哪个银行电话?40000955
4000095555是哪个银行电话?4000095555其实就是招商银行的号码,这个号码是信用卡中心服务号。一般主要用于向用户推销信用卡相关服务。400009
天天滚动:【环球财经】东京股市继续
东京股市两大股指14日继续上扬。日经225种股票平均价格指数终盘上涨1 4
生物电化学系统新型活性炭空气阴极开
生物电化学系统新型活性炭空气阴极开发与应用研究,关于生物电化学系统
忙了半天不在点儿上?金章宗究竟干啥
金章宗题顾恺之女史箴图卷 五云金碧拱朝霞, 楼阁峥嵘帝子家。 三十六
国家医保局飞行检查48家定点医疗机构
国家医保局飞行检查48家定点医疗机构追回医保基金7 2亿元---新华社北京
生物电场论_关于生物电场论介绍_天天
生物电场论,关于生物电场论介绍这个很多人还不知道,我们一起来看看!1
开户行行号在银行卡上有吗?开户行行
开户行行号在银行卡上有吗?开户银行行号通常可以在银行卡上的卡面上找到,通常是卡号下方的一串数字。银行卡卡号指的是个人办的银行卡上面的
传奇网站被拦截_浏览器被传奇私服网
1、可以重置IE浏览器,然后再清除缓存就可以了。2、可以参考以下几种方
焦点热议:潮评丨女子当街训斥环卫工
潮评丨女子当街训斥环卫工,让劳动者有尊严不能是空话潮新闻客户端评论
营业收入1000万元的税收要交多少?公
营业收入1000万元的税收要交多少?如果是服务型行业1000万的营业额的话:增值税10%,附加税等于增值税的12%,企业所得税25%,再加上红利20%,正常
税金及附加包括企业所得税吗?税金及
税金及附加包括企业所得税吗?企业所得税不属于税金及附加,企业所得税计入所得税费用;税金及附加主要核算城建税、教育费附加、地方教育费附
【世界新视野】23-24赛季30队夺冠赔
直播吧6月14日讯 近日,福克斯体育列举了23-24赛季30支球队的夺冠赔率
当前短讯!没能留住 ARM 英国欲借
但面对科技行业的新一波热潮,英国希望通过制定自己的融资和监管规则,