Working With Field Maps
Field Maps are one of the most essential pieces of GraphQL-Utils. They are a parsed version of the GraphQL AST simplified to take fragments into account as well as remove the extra data we aren't interested in.
You can read more about the FieldMap
interface here.
In order to retrieve the field map we can use the resolveFieldMap()
helper, which takes info
as its only required argument, and we may additionally specify whether a deep field map should be parsed, so we can check nested data and calculate the cost of a query, or just a single layer for example to help us optimize our SQL SELECT
and JOIN
queries.
#
Resolving A Field MapIn order to resolve a field map, all we need to do is use the info
argument passed to our GraphQL resolvers, and retrieve the field map using the resolveFieldMap()
helper, we can pass various options to adjust the output.
Let's take a look at an example query:
#
DeepIf we want the deep field map without any additional configuration, all we need to do is call resolveFieldMap()
with our info
object:
This will output the following field map:
Now, if we want to know which columns to SELECT
from our database, we can use a simple filter to only retrieve those fields without subselections, and then print those keys:
Our output will be as follows:
#
FlatWe can also resolve a flat field map, if we only want to use it to e.g. optimize SQL queries. The flat field map will be able to tell us which columns we need to SELECT
, which can be used in combination with a query builder like KnexJS or ORMs like MikroORM to make more efficient calls to our database.
For this we simply pass false
to the second argument of resolveFieldMap()
:
This will output the following field map:
Then, we could use Object.keys()
to get a list of all the selected fields:
Our output will be as follows:
Since author
isn't a field we can just SELECT
from our database, it might make more sense to use the deep field map to filter out fields with subselections as we showed above.
#
Under A Specified ParentIf we only want to retrieve the field map under a specified parent, we can use dot-notation or an array of strings to specify this parent. This can be useful for queries that are computed instead of direct entrypoints to database tables, and we need to get all the fields requested for each entity.
Let's change up our query a bit:
Now we can specify the parent under which we want to get our field map from with either of the two syntaxes:
"postsOverview.topPosts"
["postsOverview", "topPosts"]
The rest of how resolveFieldMap()
works is identical to the previous examples, we just need to make sure to specify deep
in the arguments:
This will output the following field map:
#
Usage with KnexJSUsing deep field maps, we can check for fields that don't have any subselections, and assume they are database columns. Using KnexJS we can build dynamic SQL SELECT
statements this way:
#
Usage with MikroORMSimilar to how we did dynamic field selections with KnexJS, we can use MikroORM's entity repository fields
and populate
options to not only dynamically SELECT
specific columns, but also pre-populated relational fields using SQL JOIN
s if we assume fields with subselections are relations in our MikroORM entities:
note
This is the barebones method of using field maps to get columns and relations to SELECT
and populate. See Resolving Selections For Use With ORMs for a more declarative approach.
#
PlaygroundQueryLive
Code
Output