Greetings lads,
Not sure if this has already been implemented?
I am trying to extract all the selected direct fields inside the resolver so that I can optimize my SQL queries with only the requested fields. I only need original field names (not aliases), but this should be after resolving all fragments.
Any clue how this can be implemented? Or planned for future release?
Here is a similar library for JS folks:
https://www.npmjs.com/package/graphql-fields
Turns GraphQLResolveInfo into a map of the requested fields.
Flattens all fragments and duplicated fields into a neat object to easily see which fields were requested at any level.
Takes into account any @include or @skip directives, excluding fields/fragments which are @include(if: $false) or @skip(if: $true).
Thank you.
I believe what you are looking for is being implemented in #1446, assuming you are using the IQueryable type to optimize the SQL query. If you want to get the fields directly, this can be done with the CollectFields method. The mentioned pull request uses CollectFields and translates it to a visitor, while my example at https://github.com/TheJayMann/HotChocolate/blob/master/HotChocolate.Types.Projections/QueryableProjectionMiddleware.cs iterates over the results recursively storing them in a tree structure.
Hi @TheJayMann. Thank you for your reply.
Yes, I need to get the list of all child fields selected within the currently resolving parent field.
Also, this needs to include fields from fragments and exclude skipped/ignored fields.
When do you think this feature will be available?
@geekox86 it is in the latest 10.4 preview
@TheJayMann it would be cool when you can give it a go and give us feedback :)
@PascalSenn Awesome! I am using v11-preview.106
Is it also available in this version?
Would you please give some hints on how to use it? Which class at least?
@geekox86 it's not yet available in 11 previews. In 11 it will work differently :)
In 10.4 previews you can either do
descr.Field(x=>x.Name).UseSelection()
Or you can do
public class Foo {
[UseSelection]
public IQueryable<Bar>(
[Service]DbContext ctx)=>ctx.Bars);
}
You can use filtering and sorting also nested if you initialize it on a field that has no custom resolver.
public class BarType : ObjectType<Bar>{
public override Configure(
IObjectTypeDescriptors<Bar> desc) {
desc.Field(x=> X.NestedList)
.UsePaging()
.UseFiltering()
.UseSorting();
}
}
@PascalSenn I do not use IQueryable with my database. I actually use Dapper.
Is there a way to access the selection fields from within the resolver?
Currently, I managed to inject the IResolverContext and it has the CollectFields method.
What should I do with it to get a list of all child fields for the resolver field (after fragment and skip/ignore directive resolution)?
Sorry didn't mean to close the issue, it's difficult to use github on the phone though 👍
Custom resolvers, called computed fields, that depends on the parent are also not supported.
public class User{
public string Name {get;set;}
public string LastName {get;set;}
//NOT SUPPORTED
public string DisplayName()
=> Name + LastName;
//NOT SUPPORTED
public string DisplayName2([Parent]User user) => user.Name +user.LastName;
}
@geekox86 This is what collect fields does
You have to pass in the type + the selection set :)
You find everything on the resolver context
I will give you and example later
@PascalSenn Thank you so much :)
I always get error on the first line saying:
Unable to cast object of type 'HotChocolate.Types.NonNullType' to type 'HotChocolate.Types.ObjectType`1[System.Collections.Generic.IEnumerable`1[OeMis.OrganizationModule.Organization]]'.
Code:
public async Task<IEnumerable<Organization>> Organizations(
[Service] IOrganizationRepository organizationRepository,
IResolverContext context,
HashId? parentOrganizationId
)
{
var fields = context.CollectFields((ObjectType<IEnumerable<Organization>>) context.Field.Type, context.FieldSelection.SelectionSet);
return await organizationRepository.GetByParentOrganizationId(parentOrganizationId);
}
@geekox86 Close ;)
Try this:
public static bool TryCollectFields(
this IResolverContext context,
out IReadOnlyList<IFieldSelection> selection)
{
if (context.Field.Type.NamedType() is ObjectType objectType)
{
selection = context.CollectFields(objectType);
return true;
}
selection = null;
return false;
}
@PascalSenn Fantastic! Thank you :)
So, this should take into consideration fragments, @skip, and @ignore, correct?
But for interfaces and unions, then I have to figure out the result type myself.
Any near plan to include this useful feature in v11-preview?
@PascalSenn Just out of curiosity, what is the difference between these:
Field.Type
Field.Type.NamedType
Field.DeclaringType
Also, between these:
Field.ClrType
Field.DeclaringType.ClrType
@geekox86
So, this should take into consideration fragments, @Skip, and @ignore, correct?
yes it does.
Any near plan to include this useful feature in v11-preview?
you mean with handling interfaces and unions? If so this is already in. You just ask the schema for the possible types and get the possible selections for the possible types.
Field.Type => The type of the field for instance [String]
Field.Type.NamedType => The named type component... if the type is [String] than the named type component is String.
Field.DeclaringType => The schema type that declares the field.
Also, between these:
Field.ClrType => The .NET CLR Type Representation ... so basically the .NET type that represents the GraphQL Type in the runtime.
Field.DeclaringType.ClrType => Like for the field just now this is the runtime type representation for the type that declares the field.
Can we close this issue?
Sure. I really appreciate your time and knowledge sharing (f)
@PascalSenn The only thing currently preventing me from trying it out is that nuget.org doesn't have 10.4.0-preview-17 yet (though it does appear to have 11.0.0-preview-107 which was release after), and I'm not entirely certain the proper command for easily building the source of the release into a list of nuget packages. I could build each project specifying to create a package for each, but didn't want to go through the trouble if there were a simpler way.
10.4 preview 17 is now available
@TheJayMann btw. are you on our slack channel?
It's the fastest way to get feedback through :)