Andrew Daniel
twitter.com/ajdaniel
slides.com/ajdaniel/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
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 can bundle lots of data into one query instead of many
POST /graphQl
{
pins(last: 10) {
imgUrl
name
likes
}
}
O = 1
Strongly typed schema
No under-fetching and over-fetching
Passionate community
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
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
}
}
}
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');
}
}
};
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
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:
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:
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
http://graphql.github.io/code/
Lots of libraries are out there for different technology implementations
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
Production-ready set of tools and libraries, built upon the GraphQL specification
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
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>
);
Within IBM:
IBM Cloud Account microservice
SoftLayer VSI & bare metal provisioning microservice
Watson IoT (in development)
IBM Cloud IAM (in development)
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
slides.com/ajdaniel/graphql