GraphQL stands for Graph Query Language. It allows the creation and consumption of APIs. It provides an interface between the client and the server for data fetching and manipulations (client-server model). It is an alternative to REST and web services. It designates both the query language and the runtime.
Facebook created GraphQL in 2012. It was meant to improve mobile applications. GraphQL was open sourced in 2015.
The language allows clients to define the exact shape of required data (GraphQL is declarative). It means you can selectively define fields you are interested in, and only those will be returned from the server. This avoids both the problems of over-fetching as well as under-fetching of data.
GraphQL is hierarchical. It can follow relationships between entities. A single GraphQL query can return related entities.
GraphQL is strongly typed. It provides an additional way (beside the shape and relationships) to describe the data and its correctness.
GraphQL has a JSON-like syntax.
GraphQL can perform read and write operations. Queries are read operations to fetch data from the server. Mutations are write operations to modify the data on the server. If an operation doesn't include a type, GraphQL will treat it as a query.
Here's an example of a GraphQL query and a server response that corresponds to it. Notice the query and the response have the same shape/structure.
{
author {
name
age
posts {
title
published_at
}
}
}
{
"data": {
"author": {
"name": "Zaiste",
"age": 17,
"posts": [
{
"title": "GraphQL 101",
"published_at": "2017-07-24 11:59:21"
},
{
"title": "Immutable Infrastructure 101",
"published_at": "2017-07-17 11:59:21"
}
]
}
}
}
A GraphQL query can have a name. It is recommended to mark queries with the query
keyword and name them so it is clear what they do. GraphQL queries can have comments.
query FetchAuthor {
author {
# Fetch only the author name
name
}
}
GraphQL query consists of fields, e.g. name
or age
from the previous example. Queries can accept arguments (which can be either required or optional).
{
author(id: 9) {
name
age
}
}
Queries can have variables to make the arguments dynamic. Variables must be prefixed with $
sign followed by their type. They can have default values. !
designates $authorId
as required.
query FetchAuthor($authorId: Int! = 9) {
author(id: $authorId) {
name
age
}
}
Aliases allow to fetch data from the same field, but with different arguments by using custom names.
{
bunia: author(id: 1) {
name
age
}
zaiste: author(id: 9) {
name
age
}
}
Fragments are named set of fields to avoid repetition.
{
bunia: author(id: 1) {
...personal
}
zaiste: author(id: 9) {
...personal
}
}
fragment personal on Author {
name
age
}
Directives in GraphQL provide a way to conditionally change the shape of queries. There are two directives available so far in GraphQL specification. Both directives accept a Boolean argument.
@include
-> it conditionally includes a field or a fragment@skip
-> it conditionally skips a field or a fragment
query FetchAuthor($authorId: Int!, $isPrivate: Boolean!, $hasPosts: Post) {
author(id: $authorID) {
name
age @skip(if: $isPrivate)
posts @include(if: $hasPosts) {
title
}
}
}
Mutations in GraphQL allow to modify the data on the server (write operations). Once issued, the server responds with the updated data.
mutation UpdateAuthorAge($authorId: Int!, $age: Int!) {
updateAuthor(id: $authorId, age: $age) {
age
}
}
Mutations are executed serially in order to ensure data integrity, whereas queries are executed in parallel.
Schemas describe the data: what fields are available, how they are structured (their shape and relationships) and what are their types. Types allow the GraphQL server to determine whether a query is valid or not at runtime.
GraphQL comes with the following scalar types:
- Int: a signed 32‐bit integer
- Float: a signed double-precision floating-point value
- String: A UTF‐8 character sequence
- Boolean: true or false
- ID: represents a unique identifier
Fields defined as one of the scalar types cannot have fields of their own. You can define custom scalar types using the scalar
keyword.
Enumeration types or Enums are scalar types that represent a set of allowed values. They are defined using enum
keyword.
enum Topic {
JavaScript
Clojure
}
Schemas are constructed using GraphQL schema language.
type Author {
name: String!
age: Int
posts: [Post]
}