写点什么

graphql 计算指令之 @sortBy:查询中实现列表字段排序

用户头像
coder_xy
关注
发布于: 3 小时前

问题背景

在使用 graphql 进行查询的时候,很多场景需要对 list 类型字段进行排序,典型如根据时间戳排序指标数据、根据销量排序商品数据。


如下查询,如果数据源是按照 id 排序返回、而非销量,则需要硬编码实现商品排序。


query sortItemBySaleAmount($itemIdList:[Int]){    commodity{        itemList(itemIds: $itemIdList){            itemId            name            saleAmount        }    }}
复制代码

解决方案

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


定义对列表数据进行排序的指令:


directive @sortBy(comparator: String!, reversed: Boolean = false) on FIELD
复制代码


  • comparator:比较表达式、表达式参数为每个列表元素,值越大越靠后;

  • reversed:是否进行逆序排序;

  • 表达式结果为 null 的元素总是排在末尾。


使用指令排序的查询为:


query sortItemBySaleAmount($itemIdList:[Int]){    commodity{        itemList(itemIds: $itemIdList)        # reversed为true表示按照 saleAmount 递减排序        @sortBy(comparator: "saleAmount",reversed: true)        {            itemId            name            saleAmount        }    }}
复制代码


该能力可通过graphql-java-calculator进行实现,该组件基于指令系统、为 graphql 查询提供数据编排、动态计算和控制流的能力。实现代码如下:


Config wrapperConfig = DefaultConfig.newConfig().build();
DefaultGraphQLSourceBuilder graphqlSourceBuilder = new DefaultGraphQLSourceBuilder();GraphQLSource graphqlSource = graphqlSourceBuilder .wrapperConfig(wrapperConfig) .originalSchema( // 原始schema对象 GraphQLSourceHolder.getDefaultSchema() ).build();
String query = "" + "query sortItemListBySaleAmount($itemIdList:[Int]){\n" + " commodity{\n" + " itemList(itemIds: $itemIdList)\n" + " @sortBy(comparator: \"saleAmount\",reversed: true)\n" + " {\n" + " itemId\n" + " name\n" + " saleAmount\n" + " }\n" + " \n" + " originalItemList: itemList(itemIds: $itemIdList){\n" + " itemId\n" + " name\n" + " saleAmount\n" + " }\n" + " }\n" + "}";
ExecutionInput input = ExecutionInput.newExecutionInput(query) .variables(Collections.singletonMap("itemIdList", Arrays.asList(2, 1, 3, 4, 5))) .build();
ExecutionResult result = graphqlSource.getGraphQL().execute(input);
复制代码


输出:


assert Objects.equals(data.get("commodity").get("itemList").toString(),        "[{itemId=5, name=item_name_5, saleAmount=53}, {itemId=4, name=item_name_4, saleAmount=43}," +                " {itemId=3, name=item_name_3, saleAmount=33}, {itemId=2, name=item_name_2, saleAmount=23}, " +                "{itemId=1, name=item_name_1, saleAmount=13}]");
assert Objects.equals(data.get("commodity").get("originalItemList").toString(), "[{itemId=2, name=item_name_2, saleAmount=23}, {itemId=1, name=item_name_1, saleAmount=13}, " + "{itemId=3, name=item_name_3, saleAmount=33}, {itemId=4, name=item_name_4, saleAmount=43}, " + "{itemId=5, name=item_name_5, saleAmount=53}]");
复制代码


完整示例参考Example

联系反馈

欢迎大家试用graphql-java-calculator,笔者一直从事 graphql 的平台化工作,graphql-java组件的活跃 contributor,期待使用反馈建议。


其他文章:


发布于: 3 小时前阅读数: 19
用户头像

coder_xy

关注

还未添加个人签名 2018.03.27 加入

还未添加个人简介

评论

发布
暂无评论
graphql计算指令之@sortBy:查询中实现列表字段排序