写点什么

GraphQl Calculator 计算指令 @distinct:使用表达式对列表进行去重

用户头像
杜艮魁
关注
发布于: 3 小时前
GraphQl Calculator计算指令@distinct:使用表达式对列表进行去重

问题背景

在实际的业务场景中,有时候有对列表元素进行去重的需求,比如对于用户列表、每个年龄段只保留一个用户;对于商品列表、每种品类只保留一个商品。


不同的业务场景往往有不同的去重需求,本文介绍通过表达式和指令、在 graphql 查询中以配置化的方式实现对列表去重,满足需求的快速开发和即时生效。

解决方案

定义指令

graphql 提供了指令机制用于执行能力的动态拓展、指令机制类似于 java 中的注解。


我们通过定义 @distinct 指令对列表数据进行去重,该指令只可用在列表类型字段上,其命名和语义参考了java.util.stream.Stream


directive @distinct(comparator:String) on FIELD
复制代码


  • comparator:使用该表达式计算元素的唯一 key,唯一 key 相同的元素会被去重,保留有序列表第一个元素。comparator 为可选参数,当未设置该参数时使用System.identityHashCode(object)判断元素是否为相同对象。对列表元素进行去重,当元素为基本类型时、表达式变量为 key 为ele、value 为元素值。

示例查询

根据年龄对用户列表进行去重,每个年龄只保留一个用户。


query distinctUserInfoListByAge($userIds:[Int]){    consumer{        distinctUserInfoList: userInfoList(userIds: $userIds)        @distinct(comparator: "age")        {            userId            name            age            email        }    }}
复制代码

代码实现

该能力可通过graphql-calculator实现,该组件是一款轻量级、高性能的 graphql 查询计算引擎。使用该组件对原有的GraphQLSchema对象进行包装转换即可,具体步骤如下

继承 AsyncDataFetcherInterface

如果项目中使用了异步DataFetcher,则使其则继承AsyncDataFetcherInterface,并在方法实现中返回被包装的DataFetcher和使用的线程池。


public interface AsyncDataFetcherInterface<T> {
/** * Return the dataFetcher which async dataFetcher wrapped. * * @return the dataFetcher which async dataFetcher wrapped */ DataFetcher<T> getWrappedDataFetcher();
/** * Return the {@code Executor} which async dataFetcher used. * * @return the {@code Executor} which async dataFetcher used */ Executor getExecutor();}
复制代码
创建 GraphQLSource

使用配置类Config创建GraphQLSource对象,GraphQLSource包含GraphQLSchemaGraphQL,配置类可指定脚本执行引擎、计算指令引擎使用的线程池和对象转换工具。


Config wrapperConfig = DefaultConfig.newConfig().build();DefaultGraphQLSourceBuilder graphqlSourceBuilder = new DefaultGraphQLSourceBuilder();GraphQLSource graphqlSource = graphqlSourceBuilder        .wrapperConfig(wrapperConfig)        .originalSchema(GraphQLSourceHolder.getDefaultSchema())        .preparsedDocumentProvider(new DocumentParseAndValidationCache()).build();
复制代码


脚本语法使用了aviatorscript,aviator 是 graphql-java-calculator 的默认表达行引擎,可通过ScriptEvaluatorConfig自定义脚本执行引擎。

执行前校验

使用Validator对计算指令的使用进行语法校验、该校验包含 graphql 原生语法校验,建议实现CalculatorDocumentCachedProvider缓存校验结果。


完整示例参考Example


用户头像

杜艮魁

关注

wx:dugenkui 2018.03.27 加入

快手电商营销团队研发工程师,欢迎使用、关注graphql-calculator:https://github.com/dugenkui03/graphql-java-calculator

评论

发布
暂无评论
GraphQl Calculator计算指令@distinct:使用表达式对列表进行去重