M A Hossain Tonu
Software Development Lead,
Vantage Labs Dhaka
mahtonu@vantage.com
Database agnostic
Language of your API
Strongly Typed
Declarative data fetching
via one endpoint
declarative data fetching where a client specifies what data it needs to an API
Instead of multiple endpoints that return fixed data structures, a GraphQL server only exposes a single endpoint and responds with precisely the data a client asked for
Single endpoint
One API for different frontend frameworks
Efficient data loading, query defines the batch sizes
Fast development = Rapid Feature Development
Easy Design changes
Tonu
Post 1
Asad,
Post 2
Zia
Requirements are,
- Display the User name
- Display his last 2 posts
- Display two of his friends name
/users/<id>
/users/<id>/posts
/users/<id>/friends
HTTP Get
{
"user": {
"id": "qrt123ter5",
"name": "Tonu",
"age": 35,
"address": "...",
"facebook_url", "..."
}
}
Tonu
Post 1
Asad,
Zia
Post 2
Hey! I need only name!
/users/<id>
/users/<id>/posts
/users/<id>/friends
HTTP Get
{
"posts": [{
"id": "abc123trtr5",
"title": "Learn Angular",
"content": "...."
}
...
]
}
Tonu
Post 1
Asad,
Zia
Post 2
Hey! Another HTTP and I don't want that content!
/users/<id>
/users/<id>/posts
/users/<id>/friends
HTTP Get
{
"friends": [{
"id": "tyu123trtr5",
"name": "Asad",
"age": 35,
"address": "...",
"facebook_url": ""
}
...
]
}
Tonu
Post 1
Asad
Zia
Post 2
Hey! Not all those fields and friends!
HTTP POST
{
"data": {
{ "User": {
"name": "Tonu",
"posts": [
{"title":"Learn Angular"}
],
"friends": [
{"name":"Asad"},
{"name":"Zia"}
]
}
}
}
Tonu
Post 1
Asad,
Zia
Post 2
{
query {
User(id: "qrt123ter5") {
name,
posts {
title
}
friends(last: 2) {
name
}
}
}
}
You declare what you want.
GraphQL delivers what was expected.
type User {
name: String!
age: Int!
}
type Post {
title: String!
author: User!
}
type User {
name: String!
age: Int!
posts: [Post!]!
}
{
allUsers {
name
}
}
{
allUsers {
name
}
}
root field
Payload
{
"allUsers": [
{ "name": "Tonu" },
{ "name": "Zia" },
{ "name": "Asad" }
]
}
Server responds
{
allUsers {
name
age
}
}
More fields can be added
{
allUsers {
name
age
posts {
title
}
}
}
Even one-to-many relations
{
allUsers(last: 2) {
name
}
}
Supports arguments
mutation {
createUser(name: "Zia", age: 56) {
name
age
}
}
Mutations for Create, Update and Delete
"createUser": {
"name": "Zia",
"age": 56,
}
mutation {
createUser(name: "Zia", age: 56) {
id
}
}
subscription {
newUser {
name
age
}
}
{
"newUser": {
"name": "Asad",
"age": 23
}
}
type Query { ... }
type Mutation { ... }
type Subscription { ... }
type Query {
allUsers(last: Int): [User!]!
}
type Mutation {
createUser(name: String!, age: Int!): User!
}
type Subscription {
newUser: User!
}
type Query {
allUsers(last: Int): [User!]!
}
type Mutation {
createUser(name: String!, age: Int!): User!
}
type Subscription {
newUser: User!
}
type User {
name: String!
age: Int!
posts: [Post!]!
}
type Post {
title: String!
author: User!
}
In the setup, you have a single (web) server that implements the GraphQL specification. When a query arrives at the GraphQL server, the server reads the query’s payload and fetches the required information from the database. This is called resolving the query.
Legacy Systems
Microservices
3rd Party API
When the server receives a query, it will call all the functions for the fields that are specified in the query’s payload. It thus resolves the query and is able to retrieve the correct data for each field. Once all resolvers returned, the server will package data up in the format that was described by the query and send it back to the client.
HTTP POST
{
query {
User(id: "qrt123ter5") {
name,
friends(last: 2) {
name
age
}
}
}
}
User(id: String!): User
name(user: User!): String
age(user: User!): Int
friends(last: Int, user User!): [User!]!
All the lower-level networking tasks as well as storing the data should be abstracted away and the declaration of data dependencies should be the dominant part.
GraphQL IDE
https://www.graphqlbin.com/v2/new
Demo Endpoint