What is GraphQL
GraphQL is a query language for your API, and a server-side runtime for executing queries using a type system you define for your data.
Clients form requests by using the GraphQL query language, and the GraphQL server executes the request and returns the data in a response.
Features
- The GraphQL query language: basically about selecting fields on objects.
- A GraphQL service: it is created by defining types and fields on those types, then providing functions for each field on each type.
- In a GraphQL operation: the client specifies how to structure the data when it is returned by the server. This makes it possible for the client to query only for the data it needs, in the format that it needs it in.
- GraphQL request structures resemble JSON. However, GraphQL requests don’t use quotes for field names and don’t have colons separating field names and values. Responses are in JSON format.
GraphQL vs REST
We usually compare GraphQL and REST.
REST uses “resources” as its core concept. That means entities are identified by URIs. In contrast, GraphQL’s conceptual model is an entity graph. A GraphQL server operates on a single URL/endpoint, usually /graphql, and all GraphQL requests for a given service should be directed at this endpoint.
In a system like REST, you can only pass a single set of arguments - the query parameters and URL segments in your request. But in GraphQL, every field and nested object can get its own set of arguments, making GraphQL a complete replacement for making multiple API fetches.
GraphQL has three top-level operations:
- Query - read-only fetch
- Mutation - write, followed by a fetch
- Subscription - long-lived connection for receiving data
GraphQL exposes these operations via a schema that defines the capabilities of an API. A schema is comprised of types, which can be root types (query, mutation, or subscription) or user-defined types.
Developers start with a schema to define the capabilities of their GraphQL API, which a client application will communicate with.
Basic example
GraphQL service
A GraphQL service define schema and object types:
type Query {
me: User
}
type User {
id: ID
name: String
}
Along with resolver functions for each field on each type:
function Query_me(request) {
return request.auth.user
}
function User_name(user) {
return user.getName()
}
GraphQL Client
After a GraphQL service is running, it can receive GraphQL queries to and execute. For example, the query:
{
me {
name
}
}
Could produce the following JSON result:
{
"me":{
"name": "Luke Skywalker"
}
}
Basic Concepts
- The Operation Type is either query, mutation, or subscription and describes what type of operation you’re intending to do.
- The Operation Name is a meaningful and explicit name for your operation.
- fragments: (just like Functions) GraphQL includes reusable units called fragments. Fragments let you construct sets of fields, and then include them in queries where you need to.
- Variables: (
$variableName: variableType
) All declared variables must be either scalars, enums, or input object types. - Arguments: (just like arguments in Function()) In a system like REST, you can only pass a single set of arguments - the query parameters and URL segments in your request. In GraphQL, every field and nested object can get its own set of arguments. It let you fetch more specific data.
- Aliases: They let you rename the result of a field to anything you want.
- Directives: The core GraphQL specification includes exactly two directives, which must be supported by any spec-compliant GraphQL server implementation:
-
@include(if: Boolean)
Only include this field in the result if the argument istrue
. -
@skip(if: Boolean)
Skip this field if the argument istrue
.
-
GraphQL schema language
The GraphQL specification defines a human-readable schema definition language (or SDL) that you use to define your schema and store it as a string.
Every type definition in a GraphQL schema belongs to one of the following categories:
- Scalar
- Object
- This includes the three special root operation types: Query, Mutation, and Subscription.
- Input
- Enum
- Union
- Interface
Object type
The most basic components of a GraphQL schema are object types, which just represent a kind of object you can fetch from your service, and what fields it has. Like this:
type Book {
title: String
author: Author
}
type Author {
name: String
books: [Book]
}
The Query and Mutation types
Most types in your schema will just be normal object types, but there are two types that are special within a schema:
schema {
query: Query
mutation: Mutation
}
The Query type
The Query type is a special object type that defines all of the top-level entry points for queries that clients execute against your server. Like this:
type Query {
books: [Book]
authors: [Author]
}
Scalar types:
They represent the leaves of the query. GraphQL’s default scalar types are:
- 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 (serialized as a String): A unique identifier that’s often used to refetch an object or as the key for a cache. Although it’s serialized as a String, an ID is not intended to be human‐readable.
Interface type:
An Interface is an abstract type that includes a certain set of fields that a type must include to implement the interface. (Like class)
Union types:
Union types are very similar to interfaces, but they don’t get to specify any common fields between the types. union SearchResult = Human | Droid | Starship
Wherever we return a SearchResult type in our schema, we might get a Human, a Droid, or a Starship.
Input types:
In the GraphQL schema language, input types look exactly the same as regular object types, but with the keyword input instead of type:
input ReviewInput {
stars: Int!
commentary: String
}
Input type is particularly valuable in the case of mutations, where you might want to pass in a whole object to be created. Input object types can’t have arguments on their fields.
Apollo GraphQL
Apollo provides the developer platform and tools to unify your data and services into a supergraph (a single distributed GraphQL API).
Graphql Server Setup
Apollo Server is an open-source, spec-compliant GraphQL server that’s compatible with any GraphQL client. You can easily to setup a GraphQL server for test or production by using Apollo Server.
Here are the steps to create you own Graphql Server:
Setup Apollo Server
Fellowing the doc of Apollo Server, You can easily setup a GraphQL server.
Implement Schema and Resolver for Server
- You need to write code for Schema and Resolvers.
- Resolvers need to corresponse to Schema. All the Schema need to have a Resolver to response.
- Apollo can help you simplize the resolvers. For example, client query
books {title}
, your resolver can just write this:books: () => db.books,
. Apollo can just sendtitle
instead all fields.
Setup for Using Query Variable
What you need is a query type schema and responsed resolver. query type schema:
type Query {
game_by_title(title: String!): Game
}
You resolver:
game_by_title(_, args) {
return db.games.find((game) => game.title === args.title)
}
Now, you can run QUERY plus Variable JSON to query data from client side. For example:
query GGame($title: String!) {
game_by_title(title:$title) {
id
platform
}
}
Variable:
{
"title": "Pokemon Scarlet"
}
You can get the response from Server.
Setup for Getting related data
- You need to define the related data in your schema OBJECT type.
- you need to implement resolver for that related data as well.
- You will use
parent
parameter in your resolver.
- You will use
Set up Mutation
It is similar to Query.
- It need define type in schema using
Mutation
. - It need corresponsed resolver.
- When you add item, you may need
input
type. Like this:input AddGameInput { title: String!, platform: [String!]! }
For example add a new game, send command from client:
mutation addAGame($agame: AddGameInput!){
addGame(game: $agame){
title
id
}
}
variable:
{
"agame": {
"title": "new name",
"platform": ["Switch"]
}
}
Some concepts from Apollo GraphQL
What is Apollo Client
Apollo Client is a state management library for JavaScript. It enables you to manage both local and remote data with GraphQL. Use it to fetch, cache, and modify application data. And also it can help automatically updating your UI.
Basic idea is: (For example, React lib)
- provide context
ApolloProvider
to wrap your whole app, then you can use data everywhere. - Apollo Client provide useQuery hook to query data.
import { useQuery, gql } from '@apollo/client';
function DisplayLocations() {
const { loading, error, data } = useQuery(GET_LOCATIONS);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error : {error.message}</p>;
return data.locations.map(({ id, name, description, photo }) => (
<div key={id}>
<h3>{name}</h3>
<img width="400" height="250" alt="location-reference" src={`${photo}`} />
<br />
<b>About this location:</b>
<p>{description}</p>
<br />
</div>
));
}
Whenever this component renders, the useQuery
hook automatically executes our query and returns a result object containing loading, error, and data properties. When the result of your query comes back, it’s attached to the data property.
What is Apollo Federation?
Apollo Federation lets you declaratively combine multiple GraphQL APIs into a single, federated graph. This federated graph enables clients to interact with multiple APIs through a single request.
A client makes a request to the single entry point of the federated graph called the router. The router intelligently orchestrates and distributes the request across your APIs and returns a unified response. For a client, the request and response cycle of querying the router looks the same as querying any GraphQL server.
What’s in a supergraph?
Every supergraph uses an open architecture called Apollo Federation, which consists of the following parts:

- The graph router
- One or more subgraphs
- Backing data sources (databases, REST APIs, etc.)
What is Apollo GraphOS?
Apollo GraphOS is the platform for building, managing, and scaling a supergraph: a network of your microservices and their data sources—all composed into a unified GraphQL API.
FAQ
How to use fragment
Here’s the declaration of a NameParts
fragment that can be used with any Person
object:
fragment NameParts on Person {
firstName
lastName
}
Every fragment includes a subset of the fields that belong to its associated type. In the above example, the Person
type must declare firstName
and lastName
fields for the NameParts
fragment to be valid.
We can now include the NameParts
fragment in any number of queries and mutations that refer to Person
objects, like so:
query GetPerson {
people(id: "7") {
...NameParts
avatar(size: LARGE)
}
}
Based on our NameParts
definition, the above query is equivalent to:
query GetPerson {
people(id: "7") {
firstName
lastName
avatar(size: LARGE)
}
}