github.com/maeglindeveloper/gqlgen@v0.13.1-0.20210413081235-57808b12a0a0/docs/content/reference/field-collection.md (about)

     1  ---
     2  title: 'Determining which fields were requested by a query'
     3  description: How to determine which fields a query requested in a resolver.
     4  linkTitle: Field Collection
     5  menu: { main: { parent: 'reference', weight: 10 } }
     6  ---
     7  
     8  Often it is useful to know which fields were queried for in a resolver.  Having this information can allow a resolver to only fetch the set of fields required from a data source, rather than over-fetching everything and allowing gqlgen to do the rest.
     9  
    10  This process is known as [Field Collection](https://facebook.github.io/graphql/draft/#sec-Field-Collection) — gqlgen automatically does this in order to know which fields should be a part of the response payload.  The set of collected fields does however depend on the type being resolved.  Queries can contain fragments, and resolvers can return interfaces and unions, therefore the set of collected fields cannot be fully determined until the type of the resolved object is known.
    11  
    12  Within a resolver, there are several API methods available to query the selected fields.
    13  
    14  ## CollectAllFields
    15  
    16  `CollectAllFields` is the simplest way to get the set of queried fields.  It will return a slice of strings of the field names from the query.  This will be a unique set of fields, and will return all fragment fields, ignoring fragment Type Conditions.
    17  
    18  Given the following example query:
    19  
    20  ```graphql
    21  query {
    22      foo {
    23          fieldA
    24          ... on Bar {
    25              fieldB
    26          }
    27          ... on Baz {
    28              fieldC
    29          }
    30      }
    31  }
    32  ```
    33  
    34  Calling `CollectAllFields` from a resolver will yield a string slice containing `fieldA`, `fieldB`, and `fieldC`.
    35  
    36  ## CollectFieldsCtx
    37  
    38  `CollectFieldsCtx` is useful in cases where more information on matches is required, or the set of collected fields should match fragment type conditions for a resolved type.  `CollectFieldsCtx` takes a `satisfies` parameter, which should be a slice of strings of types that the resolved type will satisfy.
    39  
    40  For example, given the following schema:
    41  
    42  ```graphql
    43  interface Shape {
    44      area: Float
    45  }
    46  type Circle implements Shape {
    47      radius: Float
    48      area: Float
    49  }
    50  union Shapes = Circle
    51  ```
    52  
    53  The type `Circle` would satisfy `Circle`, `Shape`, and `Shapes` — these values should be passed to `CollectFieldsCtx` to get the set of collected fields for a resolved `Circle` object.
    54  
    55  > Note
    56  >
    57  > `CollectFieldsCtx` is just a convenience wrapper around `CollectFields` that calls the later with the selection set automatically passed through from the resolver context.
    58  
    59  ## Practical example
    60  
    61  Say we have the following GraphQL query
    62  
    63  ```graphql
    64  query {
    65    flowBlocks {
    66      id
    67      block {
    68        id
    69        title
    70        type
    71        choices {
    72          id
    73          title
    74          description
    75          slug
    76        }
    77      }
    78    }
    79  }
    80  ```
    81  
    82  We don't want to overfetch our database so we want to know which field are requested.
    83  Here is an example which get's all requested field as convenient string slice, which can be easily checked.
    84  
    85  ```golang
    86  func GetPreloads(ctx context.Context) []string {
    87  	return GetNestedPreloads(
    88  		graphql.GetOperationContext(ctx),
    89  		graphql.CollectFieldsCtx(ctx, nil),
    90  		"",
    91  	)
    92  }
    93  
    94  func GetNestedPreloads(ctx *graphql.OperationContext, fields []graphql.CollectedField, prefix string) (preloads []string) {
    95  	for _, column := range fields {
    96  		prefixColumn := GetPreloadString(prefix, column.Name)
    97  		preloads = append(preloads, prefixColumn)
    98  		preloads = append(preloads, GetNestedPreloads(ctx, graphql.CollectFields(ctx, column.Selections, nil), prefixColumn)...)
    99  	}
   100  	return
   101  }
   102  
   103  func GetPreloadString(prefix, name string) string {
   104  	if len(prefix) > 0 {
   105  		return prefix + "." + name
   106  	}
   107  	return name
   108  }
   109  
   110  ```
   111  
   112  So if we call these helpers in our resolver:
   113  ```golang
   114  func (r *queryResolver) FlowBlocks(ctx context.Context) ([]*FlowBlock, error) {
   115  	preloads := getPreloads(ctx)
   116  ```
   117  it will result in the following string slice:
   118  ```
   119  ["id", "block", "block.id", "block.title", "block.type", "block.choices", "block.choices.id", "block.choices.title", "block.choices.description", "block.choices.slug"]
   120  ```