- the query is shaped just like the data it returns; it returns exactly what a client asks for
- declarative data fetching
- provides a separation of structure(schema - abstract descr of server's capabilities) and behavior(actual implementation - resolvers)
- solves the over-fetching problem: the client downloads more information than needed
- solves the under-fetching problem: a specific endpoint does not provide enough of the required information which results in making additional requests
- contains operations(subscriptions, queries, mutations) as well as fragments
- describes one piece of information
- might contain selection set (deeply nested requests)
- functions that return values
- each field is backed by a resolver
Example
{
// It can also be given an alias
andrei: user (id: 4) {
id
name
smallPic: profilePic (size: 64),
bigPic: profilePic (size: 1024)
}
}scalar: primitive valuesobject(can be used as output type): set of fieldsinputinterface(can be used as output type): defines a list of fieldsunion(can be used as output type): one of the possible types will be returnedenum: allow the schema to define exactly what data is expected
- allow the reuse of common repeated selection of fields
- can be specified on object types, interfaces and unions
- cannot be specified on any input values (scalar, enumeration, input object)
- the type of the object must match the type the fragment is operating on
- query variables can be used within fragments; query variables have global scope in a given operation
Example
query withFragments {
user (id: 4) {
friends (first: 10) {
...friendsFragment
}
mutualFriends (first: 10) {
...friendsFragment
}
}
}
// `on` - specify the type they apply to
fragment friendsFragment on User {
id
name
...standardProfilePic
}
fragment standardProfilePic on User {
profilePic(size: 50)
}- conditionally include fields based on their runtime type
Example
{
profiles (...) {
handle
... on User {
friends {
count
}
}
}
}- read-only fetch
- describe a tree of information
- a write followed by a fetch
Example
Like a blog post then receive the new number of likes
{
mutation {
likePost (postID: 12345) {
post {
likeCount
}
}
}
}- long-lived request that fetches data in response to source events
-
provide a way to describe/alternate runtime execution and type validation behavior;example: conditionally including/skipping a field
Example
query myQuery ($someVal: Boolean) { # Conditional exclusion experimentalField @skip(if: $someVal): String # Conditional inclusion anotherField @include(if: $someVal): Int }
-
must be used in the locations they are defined to belong in
Example
directive @example on FIELD fragment someFragment on SomeType { field @example // FIELD } // ====== // Can also annotate field and argument definitions directive @example on FIELD_DEFINITION | ARGUMENT_DEFINITION type SomeType { field (arg: Int @example): String @example # FIELD_DEFINITION }
- defines what types and directives it supports
- defines root operation types: query, mutation, subscription
- each document must include a schema definition
schema { query: MyQueryRootType mutation: MyMutationRootType }
- a contract between the client and the server; defines how a client can access the data