Reputation: 2773
I have a graphql query that has two fields. They come from separate, slow sources and either or both of them may result in an error, represented as null in this example.
If one or both fields is non-null, then I would like to return the value(s) that I can. If both are null, then I would like to return a GraphQL error. I can do that using a query like so:
[ExtendObjectType(OperationTypeNames.Query)]
public class FooQuery
{
[GraphQLName("searchFoo")]
public async Task<Foo> SearchFoo(FooRequest request)
{
var foo = new Foo {
Bar = GetBar(), // Slow, may return null
Baz = GetBaz() // Slow, may return null
}
if (Bar == null && Baz == null) {
throw new GraphQLException(...);
}
return foo;
}
}
It may be that the user is only interested in Bar
and therefore hasn't included Baz
in their request.
Q: Is there a way that I can detect the fields that have been asked for, and shortcut the processing of Baz
?
I am aware that this would mean an error response for Bar
would result in the whole query returning an error, even if data is actually available for Baz
. We've already got clients calling this query, so I'd rather not split it into separate queries as that would require changes in the client code which I do not have control over.
Upvotes: 2
Views: 129
Reputation: 2773
Based on the video by @Michael Ingmar Staib, this can be done in two ways.
Hot Chocolate 13
[ExtendObjectType(OperationTypeNames.Query)]
public class FooQuery
{
[GraphQLName("searchFoo")]
public async Task<Foo> SearchFoo(FooRequest request, IResolverContext context)
{
var selections = context.GetSelections((ObjectType)context.Selection.Type.NamedType());
var hasSelectedBaz = selections.Any(t => t.Field.Name.Equals("baz"));
var foo = new Foo {
Bar = GetBar(), // Slow, may return null
Baz = hasSelectedBaz ? GetBaz() : null // Slow, may return null
}
if (Bar == null && Baz == null) {
throw new GraphQLException(...);
}
return foo;
}
}
Hot Chocolate 14
[ExtendObjectType(OperationTypeNames.Query)]
public class FooQuery
{
[GraphQLName("searchFoo")]
public async Task<Foo> SearchFoo(FooRequest request, [IsSelected("baz")] hasSelectedBaz)
{
var foo = new Foo {
Bar = GetBar(), // Slow, may return null
Baz = hasSelectedBaz ? GetBaz() : null // Slow, may return null
}
if (Bar == null && Baz == null) {
throw new GraphQLException(...);
}
return foo;
}
}
Upvotes: 1
Reputation: 1927
This can be done with the selections api in Hot Chocolate 14.
Here is a youtube episode that shows how it works. https://youtu.be/XZVpimb6sKg
Upvotes: 1