GraphQL 101
Andrew Daniel
twitter.com/ajdaniel
slides.com/ajdaniel/graphql
About this presentation
- This is an introduction to GraphQL
- An overview of the benefits of GraphQL
- A simple example of it in use
- An introduction to Apollo GraphQL
- Some code snippets of Apollo in Node & React
- No running code shown
- No in-depth details
- Just a simple introduction to spark your interest
- I am not an Expert! We're implementing this in Watson Compare & Comply service
What is GraphQL
In a nutshell:
GraphQL is a replacement for REST
GraphQL uses a QUERY LANGUAGE
GraphQL is a PATTERN not a technology
Created by Facebook in 2012
Why choose GraphQL?
REST in applications has a disadvantage with lots of information to display on one screen
One API Call for collection
Then one call per item for details
O = n + 1
GET /results
GET /results/1234
GET /results/5678
GET /results/9012
GraphQL vs REST
GraphQL can bundle lots of data into one query instead of many
POST /graphQl
{
pins(last: 10) {
imgUrl
name
likes
}
}
O = 1
Other benefits
Strongly typed schema
- Can be shared with client & server
- Can validate requests at build time
- Auto complete queries and mutations
- Can be mocked easily
No under-fetching and over-fetching
- Reduce those spinner times!
Passionate community
- This project has been around a while
- And will last a while too
How does it work?
Schema definition
First, you describe your data with a schema
type Query {
pins: [Pin]
}
type Pin {
id: ID
name: String
imgUrl: String
likes: Number
}
Strongly Typed
Types can be a Scalar
(boolean, string, ID)
or Object with fields
This schema can generate types in Typescript, or Flow
Resolvers
Then you create resolvers for all schema fields in your chosen language using a library that implement the data. Resolvers work at the object property level
const types = {
Query: {
pins: () => {
return db.get.pins()
}
}
Pin: (pinData) => {
return {
id: pinData._id,
name: pinData.name.toLowerCase()
likes: pinData.likes.length
}
}
}
Deeper example
const resolvers = {
Query: {
documents: (parent, args, context) => context.wds.getDocuments(args)
},
Document: {
title(doc) {
return doc.extracted_metadata.title;
},
filename(doc) {
return doc.extracted_metadata.filename;
},
date(doc) {
return doc.extracted_metadata.publicationdate;
},
elements: async (doc, args, context) => {
const elements = _get(doc, 'enriched_html_elements.elements');
if (elements !== undefined) {
return elements;
}
const document = await context.wds.getDocumentById(doc.id);
return _get(document, 'enriched_html_elements.elements');
}
}
};
Query the data
Finally, your client can request the data, and query which data it likes
POST /graphql
{
pins {
name
imgUrl
likes
}
}
Retrieve pins, for each pin return the name, image url, and the number of likes
Data returned
The data returned matches the query structure
{
"data": {
"pins": [{
"name": "Batman poster",
"imgUrl": "https://imgur.com/8sduf.png",
"likes": 8
}, {
"name": "Bat suit",
"imgUrl": "https://imgur.com/34dhh.png",
"likes": 25
}]
}
}
Queries:
- Retrieve data
- Specify which fields are returned
- Can pass in variables, great for pagination
query HeroNameAndFriends($episode: Episode) {
hero(episode: $episode) {
name
friends {
name
}
}
}
{
"episode": "JEDI"
}
{
"data": {
"hero": {
"name": "R2-D2",
"friends": [
{
"name": "Luke Skywalker"
},
{
"name": "Han Solo"
}
]
}
}
}
Query
Variables
Response
Mutations:
- Alter data
- Can also specify return properties
- Pass in variables
mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
createReview(episode: $ep, review: $review) {
stars
commentary
}
}
{
"ep": "JEDI",
"review": {
"stars": 5,
"commentary": "This is a great movie!"
}
}
{
"data": {
"createReview": {
"stars": 5,
"commentary": "This is a great movie!"
}
}
}
Mutation
Variables
Response
Putting it into practice
Libraries
http://graphql.github.io/code/
Lots of libraries are out there for different technology implementations
Connectors
Out of the box solutions (or make your own) to apply a GraphQL API on top of databases or APIs.
Prisma is a leading library for SQL, NoSQL and Elastic DBs
Apollo GraphQL
Production-ready set of tools and libraries, built upon the GraphQL specification
Apollo GraphQL
Example with NodeJS + Express
npm install --save apollo-server-express@1 graphql-tools graphql express body-parser
https://www.apollographql.com/docs/apollo-server/example.html
const express = require('express');
const bodyParser = require('body-parser');
const { graphqlExpress } = require('apollo-server-express');
const { makeExecutableSchema } = require('graphql-tools');
const books = [
{
title: "Harry Potter and the Sorcerer's stone",
author: 'J.K. Rowling',
},
{
title: 'Jurassic Park',
author: 'Michael Crichton',
},
];
server.js
const typeDefs = `
type Query { books: [Book] }
type Book { title: String, author: String }
`;
const resolvers = {
Query: { books: () => books },
};
const schema = makeExecutableSchema({ typeDefs, resolvers });
const app = express();
app.use('/graphql', bodyParser.json(), graphqlExpress({ schema }));
app.listen(3000, () => {
console.log('Go to http://localhost:3000/graphiql to run queries!');
});
Fetch data with GraphiQL:
Powerful GraphQL viewer, like Postman
React Client
npm install apollo-boost react-apollo graphql-tag graphql --save
import ApolloClient from "apollo-boost";
const client = new ApolloClient({
uri: "https://w5xlvm3vzz.lp.gql.zone/graphql"
});
import React from "react";
import { render } from "react-dom";
import { ApolloProvider } from "react-apollo";
const App = () => (
<ApolloProvider client={client}>
<BookList />
</ApolloProvider>
);
render(<App />, document.getElementById("root"));
import { Query } from "react-apollo";
import gql from "graphql-tag";
const query = gql`
{
books {
title
author
}
}
`
const BookList = () => (
<Query query={query}>
{({ loading, error, data }) => {
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
return data.books.map(({ title, author }) => (
<div key={title}>
<p>{`${title} - ${author}`}</p>
</div>
));
}}
</Query>
);
Where is it used?
Within IBM:
IBM Cloud Account microservice
SoftLayer VSI & bare metal provisioning microservice
Watson IoT (in development)
IBM Cloud IAM (in development)
Resources
GraphQL site
https://graphql.org/learn/
Apollo GraphQL site
https://www.apollographql.com/
How to GraphQL - great tutorial
https://www.howtographql.com/
IBM FED presentation on GraphQL
https://jlengstorf.github.io/presentations/better-data-layer
Questions?
Thank you
slides.com/ajdaniel/graphql