写点什么

graphql 计算指令之 @skipBy 和 @includeBy:使用表达式实现简单控制流

用户头像
coder_xy
关注
发布于: 43 分钟前
graphql计算指令之@skipBy和@includeBy:使用表达式实现简单控制流

问题背景

graphql 内置了 @skip 和 @include 来决定是否跳过某个字段的解析获取,其参数为 bool 类型,但是真实的业务场景往往更加复杂。比如我们想让 userId 在 100 以内的用户才可以看到优惠券,或者通过配置化的方式来判断查询使用的版本参数可以获取到哪些字段。


如下查询,期望只有 v2 版本的客户端才可以看到,这个逻辑要不在 email 对应的 DataFetcher 中实现,要不直接获取、返回多余数据。第一种方式都不够灵活,第二种方式当 email 获取成本大时将不可接受、例如有一次网络调用。


query userInfoQuery($userId:Int){    consumer{        userInfo(userId: $userId){            userId            age            name            email        }    }}
复制代码

解决方案

graphql 提供了指令机制,该机制类似于 java 注解,可用于 graphql 查询执行能力的动态拓展。


定义是去获取某个字段的指令:


directive @includeBy(predicate: String!, dependencySources:[String!]) on FIELD
复制代码


  • predicate:判断是否解析该字段的表达式,表达式参数为查询变量(和其他 @fetchSource:进阶使用,将在以后介绍);


@includeBy 是 graphql 内置指令@include的扩展版本,可通过表达式判断是否请求该字段,表达式参数为查询变量和其他 @fetchSource。


@fetchSource 为进阶使用,参考grapqhl-calculator README


使用 @includeBy 查询如下,只有表达式为 true 时,email 对应的 DataFetcher 才会执行


query queryMoreDetail_case01($userId:Int,$clientVersion:String){    consumer{        userInfo(            userId: $userId,            # 受限于graphql原生语法校验,变量必须被明确的作为参数使用            clientVersion: $clientVersion){            userId            age            name            # 只在v2版本的客户端中展示            email @includeBy(predicate: "clientVersion == 'v2'")        }    }}
复制代码


该能力可通过graphql-java-calculator进行实现,该组件基于指令系统、为 graphql 查询提供数据编排、动态计算和控制流的能力。实现代码参考@includeBy exmaple,框架使用完整示例参考Example

联系反馈

笔者为graphql-java组件的活跃 contributor、主要参与了 15、16 版本的指令能力升级和语法校验完善,先后在美团、快手从事 graphql 的平台化工作。欢迎使用graphql-java-calculator,期待使用反馈和参与建设。

发布于: 43 分钟前阅读数: 7
用户头像

coder_xy

关注

还未添加个人签名 2018.03.27 加入

还未添加个人简介

评论

发布
暂无评论
graphql计算指令之@skipBy和@includeBy:使用表达式实现简单控制流