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