Skip to content

Instantly share code, notes, and snippets.

@joaquimds
Last active February 26, 2024 16:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joaquimds/3ed930a7f979463acc33e8bea1057917 to your computer and use it in GitHub Desktop.
Save joaquimds/3ed930a7f979463acc33e8bea1057917 to your computer and use it in GitHub Desktop.

GraphQL Intro

3 Core Concepts:

  • Types: What kinds of things are returned by the API?
  • Schema: How can the API be queried, and how are the types related to each other?
  • Requests: What does a GraphQL API request look like?
  • Resolvers: How does GraphQL get the data from the data source?

Types

A Type is an Object with specific properties. It looks like a typescript interface:

E.G.:

Fruit {
  id: int
  name: string
  color: Color
}

Color {
  id: int
  name: string
}

Schema

The Schema defines the Graph - i.e. the Types and how they are connected It also defines the shape of the Query.

It looks a bit like JSON but is not JSON. No commas after each property!

e.g.

The schema must have some root level properties. These define what queries are allowed.

Here is an example root schema, which is the special Query type:

Query {
  fruits: List[Fruit]
  fruit(id: int): Fruit
}

There are two kinds of queries allowed:

  1. A "fruits" query, which returns a list of all Fruits
  2. A "fruit" query, which gets a fruit by id

Requests

Our Schema overall looks like this:

Fruit {
  id: int
  name: string
  color: Color
}

Color {
  id: int
  name: string
}

Query {
  fruits: List[Fruit]
  fruit(id: int): Fruit
}

An example request looks like this:

  1. Give me all the fruit ids and names
POST {
  fruits {
    id
    name
  }
}
  1. Give me a specific fruit name
POST {
  fruit(id:1) {
    name
  }
}
  1. Any other request will be invalid, usually a 400 error:
POST {
  hello
}

This is an error because "Query" does not have "hello".

Also an error because "Fruit" does not have "price".

POST {
  fruits {
    price
  }
}

Resolvers

We have to tell GraphQL how to "resolve" each Type. Which means: how to get it from the data source.

e.g. in NodeJS

Recall the types:

Fruit {
  id: int
  name: string
  color: Color
}

Color {
  id: int
  name: string
}

Query {
  fruits: List[Fruit]
  fruit(id: int): Fruit
}

The resolvers have the same structure:

const resolvers = {
  Fruit: {
    id: (fruit) => fruit.id,
    name: (fruit) => fruit.name,
    color: (fruit) => {
      // fruit will look like { id: 1, name: 'Orange', color_id: 1 }
      return sql_query('SELECT * FROM colors WHERE id=?', fruit.color_id)
    }
  },
  Color: {
    id: (color) => color.id,
    name: (color) => color.name
  },
  Query: {
    fruits: () => {
      return sql_query('SELECT * FROM fruits')
    },
    fruit: (id) => {
      const fruits = sql_query('SELECT * FROM fruits WHERE id=?', id)
      if (!fruits.length) {
        throw new Error('Fruit not found')
      }
      return fruits[0]
    }
  }
}

const schema = graphql.createSchema(types, resolvers)

app.post('/graphql', (req, res) => {
  const result = schema.query(req.data)
  res.send(result)
})

Traversing the Graph

In GraphQL, you can query related objects in the same request. Compared with REST, where if you got a list of Fruits, you would have to iterate through each Fruit and make a new request to get its Color, in GraphQL you can get this with one request:

POST {
  fruits {
    id
    name
    color {
      id
      name
    }
  }
}

GraphQL will use the fruits resolver to get the list of Fruits from the database, and then for each Fruit it will use the color resolver to get the Color from the database.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment