The problem background

When using GraphQL for query, many scenarios need to sort list type fields, such as sorting index data by timestamp and commodity data by sales volume.

In the following query, if the data source is returned sorted by ID rather than by sales, the order of goods needs to be hard-coded.

query sortItemBySaleAmount($itemIdList:[Int]){
    commodity{
        itemList(itemIds: $itemIdList){
            itemId
            name
            saleAmount
        }
    }
}
Copy the code

The solution

Graphql provides a directive mechanism, similar to Java annotations, that can be used to dynamically extend graphQL’s query execution capabilities.

Define an instruction to sort list data:

directive @sortBy(comparator: String! , reversed: Boolean = false) on FIELDCopy the code
  • Comparator: Compare expressions. The expression argument is each list element. The larger the value, the later the expression.
  • Reversed: Whether the order is reversed;
  • Elements that result in null expressions are always ranked last.

The query that uses an instruction sort is:

query sortItemBySaleAmount($itemIdList:[Int]){ commodity{ itemList(itemIds: $itemIdList) @sortby (comparator: "saleAmount",reversed: true) { itemId name saleAmount } } }Copy the code

This capability is achieved through graphQL-Java-Calculator, a component based on an instruction system that provides data choreography, dynamic computation, and control flow capabilities for GraphQL queries. The implementation code is as follows:

Config wrapperConfig = DefaultConfig.newConfig().build();

DefaultGraphQLSourceBuilder graphqlSourceBuilder = new DefaultGraphQLSourceBuilder();
GraphQLSource graphqlSource = graphqlSourceBuilder
        .wrapperConfig(wrapperConfig)
        .originalSchema(
                // The original Schema object
                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);
Copy the code

Output:

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}]"
);

Copy the code

See Example for a complete Example.

Contact the feedback

Welcome to try graphqL-Java-Calculator. The author has been engaged in the platform work of GraphQL in Meituan and Kuaishou successively. As an active contributor of GraphQL-Java component, I look forward to feedback and suggestions.

Other articles:

  • # graphQL computation directive @filter: implement collection filtering in query