关于数据聚合与 graphQL 的使用

2020-08-11 23:20:46 +08:00
 jiobanma

有个需求,比如我通过 userid 查数据库映射到 userBean 中,然后我还需要通过 userBean 中传回来的内容中的 groupId 查数据库映射到 groupBean 中。这个时候我可以获取到两个 java 对象( user 、group )。 普遍的做法是将两个对象塞到一个 List 中,返回给前端,前端自己过滤和拼装渲染。 其实前端想要是一个聚合后的 json 。 比如按照之前的做法我们返回给前端的 json 是这样的: { "user": { "userid": 111, "name": "张三", "age": "12", "sex": "男" }, "group": { "groupid": 222, "name": "学习组", "des": "学习小组" } }

但是现在前端想要的格式其实是 { "user": { "userid": 111, "name": "学习组", "age": "12", "sex": "男", "groupid": 222 } }

当然服务端可以通过定义一个只包含这些字段的 bean 出来,然后将两次查询到的结果分别 set 进去。但是这样会造成产生了很多返回结构体的 bean 出现。

目前了解了一下 graphQL,但是感觉后端加入这个框架写的很麻烦,网上没有太多 springboot+graphQL 的 demo 。而且感觉写法也不太简单,可能是我太菜的原因。

问下大家,后端实现数据聚合还有哪些思路? 或者是使用 graphQL 有哪些 demo 可以参考。今天看这块内容已经自闭一天了。

3217 次点击
所在节点    Java
20 条回复
Mithril
2020-08-12 00:23:45 +08:00
这种需求 GraphQL 可以直接解决。你定义 GraphQL 对象的时候直接用 User 里面嵌套一个 Group,前端需要从 User 里面获取所属 Group 的时候直接拿这个对象就可以了,GraphQL 会给它填进去。
当然很多时候你需要自己写 DataLoader 。
你如果不能用纯 Rest API 完成接口设计,那么多数是前端需要依靠后端来聚合数据。大概率是因为性能原因没办法在前端做聚合。GraphQL 本身可以帮你做一些简单的聚合,同时也可以直接减少请求次数。但是最终你很可能还是要自己写一些 DataLoader 或者构造一些用来做 VM 的 Graph Type 。
对于后端来说,用 GraphQL 不会带来太多便利,该写的还是要写。只是前端可以一定程度上自行决定返回的数据结构,你也省了很多沟通成本,提升的是整个项目的效率。
lihongming
2020-08-12 00:33:15 +08:00
私以为,GraphQL 不是给后端用的,而是应该由前端自己写的。

现在的前端早已不是那个切图仔了,大前端至少要负责到直接对外暴露的 API 那一级
optional
2020-08-12 09:04:23 +08:00
graphql 的格式就是前者,而不是后者。
jiobanma
2020-08-12 09:07:59 +08:00
@Mithril #1 问下大佬,我想这么做:接口还是传统的 rest 的接口,然后在 controller 中使用 graphql 对数据库中查询出来的数据进行聚合 聚合为一个 json 返回给前端。这样可以实现吗? 因为对 graphql 了解的不是太多,看到网上的 demo 大多都是接口传入的是类似于 json 的 graphql 的语法。
jiobanma
2020-08-12 09:08:28 +08:00
@optional #3 那是说,graphql 无法聚合为后者那样的格式吗?
optional
2020-08-12 09:36:00 +08:00
就像你上面说的,可以再映射一下数据格式,其实这很好的方案,graphql 直接给前端也有其它的坏处,中间加一层可以解决不少问题。而且这些映射有现成的工具可以配置。
jiobanma
2020-08-12 09:40:47 +08:00
@optional #6 主要是找不到好的 demo 看官网有点看不太懂 水平有些差
ianva
2020-08-12 09:49:22 +08:00
java 里似乎没什么好方案,我们这边全转到 node.js ,用 Apollo 了
Mithril
2020-08-12 09:50:42 +08:00
@jiobanma 你这个做法是不行的。你没法从一个 Rest Controller 里面直接调用 GraphQL 。GraphQL 也不是拿来做数据聚合用的。
它的核心就是你说的那个 JSON 语法,通过 POST 请求过来的 JSON 被解析后,GraphQL 会去调用对应的 Query,然后你这些手写的 Query 会调用和聚合相关的 Type 。
这一个链条里的 Query 和 Graph Type 都是你自己手写的,和 Rest API 用的类型是不一样的。比如按你的例子来说,你在 User 里面挂个 Group 。一般的 Rest API 只会从 User 里面返回一个 Group ID 。但你如果做成 GraphQL 接口的话,你需要自己写把这个 Group ID 转换成 Group 对象的查询。
GraphQL 会帮你在需要的时候去调用这个查询而已。
jiobanma
2020-08-12 09:53:26 +08:00
@Mithril #9 但是网上的一个 demo 他的写法是这样的:
```
public static void main(String[] args) {
String query1 = "{users(page:2,size:5,name:\"john\") {id,sex,name,pic}}";
String query2 = "{user(id:6) {id,sex,name,pic}}";
String query3 = "{user(id:6) {id,sex,name,pic},users(page:2,size:5,name:\"john\") {id,sex,name,pic}}";

GraphQLSchema schema = new HelloGraphql().getSchema();

Object result1 = GraphQL.newGraphQL(schema).build().execute(query1).getData();
Object result2 = GraphQL.newGraphQL(schema).build().execute(query2).getData();
Object result3 = GraphQL.newGraphQL(schema).build().execute(query3).getData();

// 查询用户列表
System.out.println(result1);
// 查询单个用户
System.out.println(result2);
// 单个用户、跟用户列表一起查
System.out.println(result3);
}
```
这里得到的 result 不就是我需要的结果吗? 我把这个结果返回 不就是我需要的需求吗?
Mithril
2020-08-12 09:58:43 +08:00
@jiobanma 是的。我说的你不能在 Rest Controller 里面干这个事主要是因为这是违背 Restful 的设计原则的。单独做一个 GraphQL 用的 Controller 就可以了。
你可以去看一下它的 HelloGraphql 的 Schema 和 Type 是怎么写的,那个是核心。
jiobanma
2020-08-12 10:01:48 +08:00
@Mithril #11 好的 谢谢啦
optional
2020-08-12 10:04:34 +08:00
@Mithril 实践下来,前面加一层是很有好处的,graphql 还真挺适合做聚合,做接口反倒一堆问题,监控,缓存,日志之类的
Mithril
2020-08-12 10:10:28 +08:00
@optional 其实做聚合也是一样,简单查询还行,复杂一点的你就得写 DataLoader 。
其实做接口这个事,不管你是 Restful 也好,GraphQL 也好,瞎怼也好,都只是个形式和工具。该做的事一件也不会少。
各有优缺点而已。也不是说上了 GraphQL 就万能了,只是说如果聚合和标准化是你的痛点的话,那 GraphQL 可以帮你尽量避开这些坑,但其他的坑该有也还是会有的。
jiobanma
2020-08-12 10:11:57 +08:00
@Mithril #14 嗯嗯 先试试吧 比较还在调研阶段
Mithril
2020-08-12 10:19:58 +08:00
@jiobanma 嗯。你试的时候注意一下,不要光看例子那些从内存里直接返回数据的,试着把查询打到数据库里。如果你一次返回一个对象数组,然后数组里的对象还嵌套了查询,数据库没准直接就炸了。
Data Loader 就是用来解决这个问题的。
这俩试过了,GraphQL 做查询的坑基本就趟过去了。然后就是 Mutation,权限,Log 等等。。。
jiobanma
2020-08-12 10:26:54 +08:00
@Mithril #16 Data Loader 是个什么东西啊
Mithril
2020-08-12 10:56:08 +08:00
@jiobanma GraphQL 的一个功能,你看一下 Demo 一般都有。
jilu171990
2020-08-12 12:38:50 +08:00
@lihongming 哈哈,让前端写 graphQL 的结果往往就是直接被爆库。。。
lihongming
2020-08-12 15:48:44 +08:00
@jilu171990 前端直接搞库,后端真啥都不管了啊?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/697524

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX