Let's say I have 2 tables:
- Users (id, name, post)
- Posts (id, message, user)
How can I fetch first 10 Posts order by User's name(desc)?
Here's how my schema looks like:
var PostType = new GraphQLObjectType({
name: "Post",
fields: () => ({
id: { type: GraphQLInt },
message: { type: GraphQLString },
user: {
type: UserType,
args: {
orderBy: { type: sortType }
},
resolve(parent, args) {
console.info("Post resolve called.");
return userMap[parent.user];
}
}
})
});
var RootQuery = new GraphQLObjectType({
name: "RootQueryType",
fields: {
allPosts: {
type: new GraphQLList(PostType),
resolve(parentValue, args) {
console.info("allPosts resolve called.");
return postData;
}
}
}
});
And Query:
{
allPosts {
message
user (orderBy: {field: "name", direction: ASC}) {
name
}
}
}
Is there any way, I can call user resolver function before allPosts resolver function? Because, I am trying to fetch 10 users sorted by name and then pass post ids to allPosts resolver.
You can sort GraphQL query results using an index and a user-defined function. The following example uses the following components: A GraphQL schema named schema.
Results from your query can be sorted by using the order_by argument. The argument can be used to sort nested objects too. The sort order (ascending vs. descending) is set by specifying the asc or desc enum value for the column name in the order_by input object, e.g. {name: desc} .
If you'd like to sort it in descending order, replace ASC with DESC .
GraphQL Query Filter - Where Clause You can filter the data returned by your queries with the where argument. The where argument is applied on a specific field and it filters the results based on that field's value. For example, you can use the where argument to fetch all the private todos.
GraphQL fields are resolved in a top-down fashion. That means allPosts
is resolved first, then then message
and user
fields (simultaneously) and then the name
field. This has to happen, as the "parent" or root field's resolved value determine's the value that's then passed to the resolver for its children fields as the root value. Information flows from "higher" resolvers to "lower" ones, but not the other way around.
Your orderBy
argument here probably should be an argument on the allPosts
field rather than the user
field. There's two reasons to do that: (1) conceptually, regardless of the sort criteria, you are sorting the Posts returned by allPosts
-- by convention, it just makes sense to put the sort there; (2) the argument is probably needed by the allPosts
resolver more than it's needed by the user
resolver.
To make the above work, you'll probably need to modify how you identify the sort criteria (making field
a path like user.name
for example). You may also need "lift" the logic for populating the users up into the allPosts
resolver. For example:
resolve(parentValue, { sortBy: { path, direction } }) {
const data = postData.map(post => {
post.user = userMap[post.user]
return post
});
// using lodash
return orderBy(data, [(post) => get(post, path)], [direction])
}
It is possible to determine the selection set for other fields inside the request, including the arguments, by parsing the info
object that's passed in as the fourth parameter to the resolver function. It's a pain though and I don't know if this particular case really justifies doing all that. You can read more about that approach in this answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With