graphql计算指令之@filter:查询中实现集合过滤

1,790 阅读1分钟

问题背景

在使用graphql进行查询的时候,很多场景需要对list类型字段进行过滤筛选,例如过滤下架的商品、年龄不满18岁的用户、余量为0的优惠券等。

如下查询,如果要过滤未在售(onSale==false)的商品,需要在硬编码实现。

query itemListByIds($ItemIds:[Int]){
    commodity{
        itemList(itemIds: $ItemIds){
            itemId
            onSale
            name
            salePrice
        }
    }
}

解决方案

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

定义对列表数据记性过滤的指令:predicate:过滤判断表达式,结果为true的元素会被保留。

directive @filter(predicate: String!) on FIELD

修改后的查询为:

query filterUnSaleCommodity($ItemIds:[Int]){
    commodity{
        filteredItemList: itemList(itemIds: $ItemIds)
        # 只保留在售的商品
        @filter(predicate: "onSale")
        {
            itemId
            onSale
            name
            salePrice
        }
    }
}

具体实现

该能力可通过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 filterUnSaleCommodity($itemIds:[Int]){\n" +
        "    commodity{\n" +
        "        itemList(itemIds: $itemIds)\n" +
        "        @filter(predicate: "onSale")\n" +
        "        {\n" +
        "            itemId\n" +
        "            onSale\n" +
        "            name\n" +
        "            salePrice\n" +
        "        }\n" +
        "        \n" +
        "    }\n" +
        "}";
ExecutionInput input = ExecutionInput
        .newExecutionInput(query)
        .variables(Collections.singletonMap("itemIds", Arrays.asList(1, 2, 3)))
        .build();

ExecutionResult result = graphqlSource.getGraphQL().execute(input);

完整示例参考Example

联系反馈

欢迎大家试用graphql-java-calculator,笔者先后在美团、快手从事graphql的平台化工作,graphql-java组件的活跃contributor,期待使用、建议,欢迎感兴趣的同学star关注。