REST is an architectural style. GraphQL is a data query language + framework
Overview
With GraphQL, clients can obtain all of the data they need in one request.
Whenever a query is executed against a GraphQL server, it is validated against a type system. A type system is like a blueprint for your API’s data, backed by a list of objects that you define.
1234567
type Person {
id: ID!
name: String
birthYear: String
eyeColor: String
gender: String
}
GraphQL is often referred to as a declarative data-fetching language. Developers list their data requirements as what data they need without focusing on how they’re going to get it.
GraphQL is a specification (spec) for client-server communication.
A GraphQL query is hierarchical. Fields are nested within other fields and the query is shaped like the data that it returns.
REST Drawbacks
Data overfetching and underfetching - REST either returns more data than what user needs or would require additional requests are needed to get more details. similar to N+1 problem in ORM
Managing endpoints - as the client needs change, more endpoints need to be created which eventually multiply quickly. GraphQL architecture typically involves only a single endpoint.
Like SQL, GraphQL can be used for all CRUD operations
Data Types/Operations:
Query - read
Mutation - insert, update and delete
Subscription - used to listen for data changes
A GraphQL document can contain the definitions of one or more operations. For example, one could place 2 query operations in a query document.
A JSON response can contain both “data” and “errors.”
Query
A Query data type is called a root type because it’s a type that maps to an operation, and operations represent the roots of our query document.
Selection sets
When we write queries, we are selecting the fields that we need by encapsulating them in curly brackets. These blocks are referred to as selection sets.
You can nest selection sets within one another.
Fields
The fields that are available to query in a GraphQL API have been defined in that API’s schema. The documentation will tell us what fields are available to select on the Query type.
fields can be either scalar types or object types.
Response
We can change the field names in the response object within the query by specifying an alias. e.g., liftName in below example.
Query Arguments
A way to filter the results of a GraphQL query is to pass in query arguments.
Arguments are a key–value pair (or pairs) associated with a query field.
type User { name: String!
username: String!
}type Document { title: String!
content: String!
author: User!
}
One-to-Many connections
Aa one-to-many relationship between User and Document. Notice that the documents field will contain an actual array of documents.
1234567
type User { name: String!
username: String!
email: String!
noOfDocuments: Int!
documents: [Document!]!
}
In this example, trailAccess returns a filtered list of trails that are accessible from Jazz Cat. Because trailAccess is a field within the Lift type, the API can use details about the parent object, the Jazz Cat Lift, to filter the list of returned trails.
123456789
query trailsAccessedByJazzCat { Lift(id:"jazz-cat"){ capacity
trailAccess { name
difficulty
}}}
Fragments
Resuable set of fields to include in queries.
12345678910111213141516
{ leftComparison: hero(episode: EMPIRE){ ...comparisonFields # JS spread operator} rightComparison: hero(episode: JEDI){ ...comparisonFields
}}fragment comparisonFields on Character { name
appearsIn
friends { name
}}
Union types
If you want a list to return more than one type, you could create a union type, which creates an association between two different object types.
Suppose that we’re building a scheduling app for college students with which they can add Workout and Study Group events to an agenda. When writing a query for a student’s agenda, you can use fragments to define which fields to select when the AgendaItem is a Workout, and which fields to select when the AgendaItem is a StudyGroup.
12345678910111213
query schedule { agenda { ...on Workout {# inline fragments name
reps
} ...on StudyGroup { name
subject
students
}}}
Interfaces are another option when dealing with multiple object types that could be returned by a single field. An interface is an abstract type that establishes a list of fields that should be implemented in similar object types. When another type implements the interface, it includes all of the fields from the interface and usually some of its own fields.
Introspection is the ability to query details about the current API’s schema. You can send queries to every GraphQL API that return data about a given API’s schema.
This query returns all available types in the API, including root types, custom types, and even scalar types.
12345678
query{__schema{types{namedescription}}}
To see the details of a particular type, we can run the __type query and send the name of the type that we want to query as an argument:
GraphQL is going to change your design process. Instead of looking at APIs as a collection of REST endpoints, begin looking at your APIs as collections of types.
Schema First Design
Schema First design methodology gets all teams on the same page about the data types that make up your application.
The backend team will have a clear understanding about the data that it needs to store and deliver. The frontend team will have the definitions that it needs to begin building user interfaces.
GraphQL Schema Definition Language (SDL) is same irrespective of the language or framework in which your application is built.
Schema & Types
A schema is a collection of type definitions. You can write your schemas in a JS file as a string or in any text file. These files usually carry the .graphql extension.
A type has fields that represent the data associated with each object. Each field returns a specific type of data. This could mean an integer or a string, but it also could mean a custom object type or list of types.
The exclamation point specifies that the field is non-nullable, which means that the name and url fields must return some data in each query
123456789101112
"""Defining a custom type named Photo"""typePhoto{id:ID!name:String!url:String!"Optional field to describe the photo "description:String}
Scalar types
A scalar type is not an object type. It does not have fields.
Built-in scalar types
Int, Float - return JSON numbers
String, ID (unique identifiers) - return strings.
Even though ID and String will return the same type of JSON data, GraphQL still makes sure that IDs return unique strings
the ID scalar type is used when a unique identifier should be returned.
Boolean - return boolean
Custom scalar type
In the example below, a custom scalar type: DateTime is created.
Any field marked DateTime will return a JSON string, but we can use the custom scalar to make sure that string can be serialized, validated, and formatted as an official date and time
The graphql-custom-types npm package contains some commonly used custom scalar types
enums are scalar types that allow a field to return a restrictive set of string values.
GraphQL object types are user-defined groups of one or more fields that you define in your schema. They define the shape of the JSON object that should be returned. JSON can endlessly nest objects under fields, and so can GraphQL
Connections and Lists
When you create GraphQL schemas, you can define fields that return lists of any GraphQL type
A list can contain elements of different types
Variations
[Int] - A list of nullable integer values
[Int!] - A list of non-nullable integer values
[Int]! - A non-nullable list of nullable integer values
[Int!]! - A non-nullable list of non-nullable integer values
One-to-many connections
It is a good idea to keep GraphQL services undirected when possible. This provides our clients with the ultimate flexibility to create queries because they can start traversing the graph from any node. All we need to do to follow this practice is provide a path back from User types to Photo types. This means that when we query a User, we should get to see all of the photos that particular user posted:
a union type is a type that we can use to return one of several different types.
AgendaItem combines study groups and workouts under a single type. When we add the agenda field to our Query, we are defining it as a list of either workouts or study groups.
Another way of handling fields that could contain multiple types is to use an interface.
Both union types and interfaces are tools that you can use to create fields that contain different object types.
In general, if the objects contain completely different fields, it is a good idea to use union types. They are very effective. If an object type must contain specific fields in order to interface with another type of object, you will need to use an interface rather than a union type.