GraphQL
Operation Types:
Schemas
# this is the root object{}# fields can be selected on this{ dog}# fields of that field can also be selected{ dog { name }}
Types
Query and Mutation
# query and mutation types specify fields that can be queriedtype Query { dog(name: String): Dog}type Mutation { addFriend(name: String, friend: Dog): Dog}
Scalar Types
StringIntFloatBooleanID # a special type of String, unique for each value# scalars can be added (although not all# implementations support this)scalar Date
Enums
enum Interval { YEAR DOGYEAR DAY}
Null
# an exclamation point means a field cannot be null# if the value is null, an execution error will occurtype Dog { name: String!}# error response{ errors: [ { message: "...", locations: [ { line: 1, column: 2 } ] } ]}
Objects
# object types describe objects that can be fetched and their fieldstype Dog { name: String! breed: String! # fields describe functions. The default is a function with zero # arguments, which doesn't need to be specified. Default values can be # provided to make arguments optional. age(unit: Interval = YEAR): Float!}
Lists
type Dog { # arrays are specified with square brackets friends: [Dog]}# array can be null, but dogs cannotfriends: [Dog!]# array cannot be null (will return empty array if no matches)friends: [Dog]!
Interface
# interfaces define required fieldsinterface Animal { id: ID! name: String!}# types can implement an interfacetype Dog implements Animal { id: ID! name: String! age: Float!}type Cat implements Animal { id: ID! name: String! lives: Int!}# interfaces can be the type for a fieldtype Query { GetAnimal($name: String!): Animal}# however, you can only query on fields of the interfacequery GetAnimal($name: String!) { # this will cause an error age}# inline fragments allow you to query type specific fields
Union
# a union groups types (not interfaces!), but without common fieldsunion Thing = Dog | Cat | Tree# this can be useful for tasks that can return multiple types
Input Types
# input types look like regular types, but are specified# with the input keywordinput DogInput { name: String! breed: String!}# input types are passed to mutations
Resolvers
# resolvers are functions associated with a field# if a resolver returns a scalar, then it stops. For other# types, it goes deeper (to that type's fields){ dog { name: String!, # string, stops friends: [Dog]! # object, so keeps going }}
// resolvers receive four arguments:// 1. obj is the previous object (one level up, not old)// 2. args are arguments provided in the field's query// 3. context extra, useful data// 4. info about query's execution state (use rarely){ Query: { dog(obj, args, context, info) { return api.getDog(args.id).then(data => { return new Dog(data); }); } }, Dog: { name(obj, args.context) { return obj.name } }}
Introspection
Useful for exploring the GraphQL structure.
Query
# the query operation type indicates that some gql is a queryquery { ...}# this isn't required, but is useful for clarity
# a query gets data# the query specifies the shape of the data it wantsquery { dog { breed }}# the returned object has properties of the same shape# as the query{ data: { dog: { breed: "corgi" } }}query { # you can also insert comments into a query dog}
# subquery with nested propertiesquery { dog: { name, friends: { name } }}# returns{ data: { name: 'Ralph', friends: [ { name: 'Spot' }, { name: 'Fido' } ] }}
Arguments
query { dog(id: "k9") { name, breed }}# returns dog that matches the id{ data: { dog: { name: 'Sahara' } }}
# sub-properties can also be queriedquery { dog(id: "k9") { weight(unit: KG) }}{ data: [ dog: { weight: 23 } ]}
Aliases
# properties can be aliased, which is helpful with duplicatesquery { shortDog: dog(breed: "dachsund") { name }, tallDog: dog(breed: "great dane") { name }}{ data: { shortDog: { name: 'Goliath' }, tallDog: { name: 'Tiny' } }}
Fragments
# fragments let you define partial queries, which can# be included as parts of a larger queryquery { shortDog: dog(breed: 'chihuahua') { ...quantitativeFields }}fragment quantitativeFields on Dog { height weight age}
# inline fragments can be used to specify properties# based on a type, which is useful for subtypesquery { animal { name ... on Dog { age } ... on Cat { lives } }}# these can be combined with named fragments,# which already include an "on"query { animal { name ...dogProperties ...catProperties }}fragment dogProperties on Dog { age}fragment catPropeties on Cat { lives}
Operation Name and Variables
# an operation name is like a function namequery DogData { dog { name breed age }}# operations must be named to pass dynamic variables# variables start with $.# The type of the variable must be provided.# The exclamation point indicates this variable is requiredquery DogData($name: String!) { dog(name: $name) { name breed age }}# default variables can be providedquery DogData($name: String = "Terra") { dog(name: $name) { ... }}
Meta
query { dog { # __typename returns an object's type # this is useful for queries that can return # multiple types __typename }}
Directives
# directives can be used to control whether# part of a query is includedquery DogData($name: String!, $andFriends: Boolean!, $withAge: Boolean!) { dog(name: $name) { name breed # only @include friends when andFriends is true friends @include(if: $andFriends) { name breed } # you can also $skip fields age @skip(if: $withAge) }}
Custom Directives
While GraphQL includes the @skip
and @include
directives, it is possible to write your own as well.
The exact implementation varies by GraphQL framework.
When defining a directive in a schema, it requires a name and what it can be added to (fields, types, etc.). The directive can also take arguments.
directive @yo( arg: String = "default value") on FIELD_DEFINTIONquery { dog { name @yo }}
Mutations
# while queries read data,# mutations are used for setting/modifying datamutation AddFriend($name: String!, $friend: String!) { addFriend(name: $name, friend: $friend) { # you can return the results of the mutation name friends { name } }}# an operation can contains multiple mutations# they will be run consecutively, not at the same time