This is my code ...
requested := graphql.CollectAllFields(ctx)
fmt.Printf("\nRequested Fields: %v\n", requested)
This is the graphql request ...
{user(id:"1") {name, nickname}, cars{registration}}
Just the top level fields were returned ...
Requested Fields: [name nickname]
That even the nested fields would be returned
Requested Fields: name, nickname, cars, registration
type User {
id: ID
name: String!
nickname: String
cars: [Car!]
}
type Car {
id: ID
registration: String!
}
gqlgen version? devgo version? g01.11.10This is intentional, as it is a convenience wrapper around CollectFieldsCtx to account for the most common case, where you just want to limit querying your data source by the actual fields requested. If you have a more complex use-case, use that instead.
See also our field collection docs.
@mathewbyrne,
Thank you for your reply. Using my graphql request (above) and CollectFieldsCtx, I still can't see cars.registration getting returned. (I still only see user.name and user.nickname.) It still seems like those Collect functions don't look inside the nested part of the graphql request.
Maybe I'm missing something.
E.g. If I have ...
requested := []string{}
satisfiesFields := graphql.CollectFieldsCtx(ctx, []string{"registration"})
fmt.Printf("\nSatisfies Fields: \n")
for _, f := range satisfiesFields {
requested = append(requested, f.Name)
fmt.Printf(" %v\n", f.Name)
}
I get ...
Satisfies Fields:
name
nickname
Also, if I replace "registration", with "car", "Car, "cars" or "Cars", I still get that result.
Can you give me a concrete example of what I would need to do to get the car.registration field included in the results?
Thank you for your help.
I have the same use-case.
My query:
flowBlocks {
id
block {
id
title
type
choices {
id
title
description
slug
}
}
}
}
Code
requested := graphql.CollectFieldsCtx(ctx, []string{"block", "choices"})
for _, column := range requested {
r.l.Debug(column.Name)
}
Response
2019-07-18T20:49:09.829+0200 DEBUG backend/resolver.go:71 id
2019-07-18T20:49:09.830+0200 DEBUG backend/resolver.go:71 block
Regardless of what I put in the satisfies argument I only got id and block
CollectAllFields the same problem. Looks like nested fields are not available in the SelectionSet of the param
@Baggerone After spitting through source got something working now
fields := graphql.CollectFieldsCtx(ctx, []string{"Block"})
for _, column := range fields {
r.l.Debug(column.Alias)
fields2 := graphql.CollectFields(reqCtx, column.SelectionSet, []string{"BlockChoices"})
for _, c := range fields2 {
r.l.Debug(c.Alias)
}
// graphql.CollectFields(ctx, []string{"Block"})
// for _, c := range column.SelectionSet {
// r.l.Debug(c.GetPosition().Src.Name)
// }
}
I've created some nice helpers which get's al the request fields
_Updated example on 11 May 2020: New PR for:
Also look at for most recent example: https://gqlgen.com/reference/field-collection/_
query {
flowBlocks {
id
block {
id
title
type
choices {
id
title
description
slug
}
}
}
}
We don't want to overfetch our database so we want to know which field are requested.
Here is an example which get's all requested field as convenient string slice, which can be easily checked.
func GetPreloads(ctx context.Context) []string {
return GetNestedPreloads(
graphql.GetOperationContext(ctx),
graphql.CollectFieldsCtx(ctx, nil),
"",
)
}
func GetNestedPreloads(ctx *graphql.OperationContext, fields []graphql.CollectedField, prefix string) (preloads []string) {
for _, column := range fields {
prefixColumn := GetPreloadString(prefix, column.Name)
preloads = append(preloads, prefixColumn)
preloads = append(preloads, GetNestedPreloads(ctx, graphql.CollectFields(ctx, column.Selections, nil), prefixColumn)...)
}
return
}
func GetPreloadString(prefix, name string) string {
if len(prefix) > 0 {
return prefix + "." + name
}
return name
}
So if we call these helpers in our resolver:
func (r *queryResolver) FlowBlocks(ctx context.Context) ([]*FlowBlock, error) {
preloads := getPreloads(ctx)
it will result in the following string slice:
["id", "block", "block.id", "block.title", "block.type", "block.choices", "block.choices.id", "block.choices.title", "block.choices.description", "block.choices.slug"]
Thank you, @RichardLindhout. That's helpful.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
My code does not include all selected fields somehow I forgot
preloads = append(preloads, GetNestedPreloads(ctx, graphql.CollectFields(ctx, column.Selections, nil), prefixColumn)...)
I've updated the code
I've updated the examples above since there were cases of duplicated preloads. And it's updated to the new OperationContext
Hi guys, is a way to get this fields in a middleware instead of a resolver ?
@mtatarau90 Sure, you have a ctx variable in your resolver right? Or else try a directive
https://gqlgen.com/reference/field-collection/
https://gqlgen.com/reference/directives/
@RichardLindhout i will use directives, thanks. Btw in middleware seems do not work, and gqlgen return a context error.
Most helpful comment
Thank you, @RichardLindhout. That's helpful.