2. GraphQL basics
3m

Overview

Let's jump into how works, and the components that bring a to life!

In this lesson, we will:

  • Explore the journey of how a client requests data and how a retrieves it
  • Learn about the components that make up a

Journey of a GraphQL operation

Let's imagine our frontend needs to fetch data for a particular page.

To get that data, it sends a to our . The app shapes the operation as a string that defines the selection set of it needs. Then, it sends that operation to the server in an HTTP POST or GET request.

Hand-drawn illustration depicting client-land with a browser sending a query to server-land across a network

In server-land

When our server receives the HTTP request, it first extracts the string with the . It parses and transforms it into something it can better manipulate: a tree-structured called an AST (Abstract Syntax Tree). With this AST, the server validates the against the types and in our schema.

If anything is off (e.g. a requested is not defined in the schema or the is malformed), the server throws an error and sends it right back to the app.

Hand-drawn illustration depicting server-land with the GraphQL server receiving a query and going through the necessary steps

In this case, the looks good, and the server can "execute" it. Meaning, the server can continue its process and actually fetch the data. The server walks down the AST.

For each in the , the server invokes that field's function—also called a datafetcher method in DGS. This method's mission is to "resolve" its by populating it with the correct data from the correct source, such as a database or a REST API. These don't necessarily need to live within the ; they can be hosted externally.

In this way, is a powerful bridge to REST (and other !) that ties all of your app's data together. The GraphQL API acts as the layer on top of them, providing a single interface through which multiple data sources can be queried simultaneously.

Hand-drawn illustration depicting a resolver function retrieving data from data-land

As all of the 's are resolved, the data is assembled into a nicely ordered JSON object with the exact same shape as the .

The server assigns the object to the HTTP response body's data key, and it's time for the return trip, back to our app.

Hand-drawn illustration depicting the server returning a response back to the browser in client-land

Back to client-land

Our client receives the response with exactly the data it needs, passes that data to the right components to render them, and voilà, our data is brought to life in a UI.

Now that we have a birds-eye view of the full journey from client, to server, and back, we'll take some time to zoom into the that outlines all of our server's data capabilities: the .

The GraphQL schema

The is where all the magic happens, but the schema tells us what's actually on the menu.

The schema is a collection of types and that make up the comprehensive picture of everything we can do with the data in a . No actual data lives here; just the basic skeleton of the shapes that the live data will conform to. (Think of a blueprint!)

The schema has its own language called schema definition language, or SDL. We'll take a closer look at syntax, and how to build the types and in our schema, in the next lesson.

Schema entry points

A (the thing that the client sends to the ) can either be a query, a mutation, or a subscription. A reads data, a changes data and a listens for live, streaming data.

All three map to a corresponding type in the schema: Query, Mutation and Subscription.

The Query is like our front door to a . It defines a number of , each of which represents a path we can "follow" to get some data from our GraphQL server. Each field has its own name, and specifies the kind of data it returns. This makes it really easy to pick and choose different fields, and get all the data we want at once!

We can think of the within the Query type as the list of things we can ask for from our API. Similarly, the Mutation type is the list of things we can do with our API, as we'll see in a later lesson.

Schema-first design

To build our , we'll use a "schema-first" design. That means we'll implement the project based on exactly which data our downstream consumers (like client applications running on mobile and desktop) will need. Schema-first design typically involves three major steps:

  1. Defining the schema: We identify which data our feature requires, and then we structure our schema to provide that data as intuitively as possible.
  2. Backend implementation: We build out our API using DGS and fetch the required data from whichever contain it. We'll start with hardcoded mocked data to learn the concepts, then hook our server up to a live REST data source.
  3. Consuming data: Clients are able to consume data from our API.

One of the benefits of schema-first design is that it reduces total development time by allowing frontend and backend teams to work in parallel. The frontend team can start working with mocked data as soon as the schema is defined, while the backend team develops the API based on that same schema. This isn't the only way to design a API, but we believe it's an efficient one, so we'll use it throughout this course.

Resolving schema fields with datafetchers

As we mentioned in the Journey of a , for every type and in the , we can define a datafetcher method. A datafetcher retrieves the data for a specific field. These methods have access to various : databases, REST APIs, even text files or JSON!

A datafetcher reaching out to a variety of different sources for data

Datafetchers let us define the precise logic needed to retrieve data for a , but we don't necessarily need to define a datafetcher by hand for EVERY field in our schema. We'll see how and when to define datafetcher functions in an upcoming lesson.

💾 Data!

Throughout the course, we'll build the API that serves (and updates) data for intergalactic listings and their features.

This mockup shows a row of featured listings. For each listing, we can start to see which pieces of data we need: photo, location type, overall rating, number of beds, title, cost per night, and whether it's closed for bookings.

A screenshot of Airlock, focused on the row of featured listings and their required fields

To create a view for a specific listing, we'll need a couple additional for each listing: its description, and the amenities it has to offer.

A screenshot of a single listing in Airlock, focused on two additional required fields

To represent these different pieces in , we can think about our data as a collection of objects (such as listings and amenities) and relationships between objects (such as each listing having at least one amenity).

Now, if we think of each object as a node and each relationship as an edge between two nodes, we can envision our entire data model as a collection of nodes and edges. This is called our application's graph.

To define the objects in our , we'll use a special syntax called . Let's talk more about in the next lesson.

Practice

Which of these are actions that our GraphQL server takes when it receives a request?
Which of these are situations where our GraphQL server will throw an error?
When a query executes successfully, which of these is included in the object returned by the GraphQL server?
GraphQL operations
There are three types of GraphQL operations. A 
 
 reads data. A mutation 
 
 data. A 
 
 listens for live, streaming data.

Drag items from this box to the blanks above

  • subscription

  • question

  • query

  • connection

  • screenshots

  • changes

Which of these accurately describes a graph in GraphQL?

Key takeaways

  • There are three types of : queries, and . A reads data, a changes data and a listens for live, streaming data.
  • The schema is a collection of types and that make up the comprehensive picture of everything we can do with the data in a . It is written in ().
  • A datafetcher method retrieves the data for a specific in our schema. These functions have access to various : databases, REST APIs, even text files or JSON. These data sources don't need to live within the .
  • enables us to build APIs by describing our data in terms of (nodes) and relationships (edges).

Up next

This course is all about building a , so let's get into the syntax! It's time to dive into .

Previous

Share your questions and comments about this lesson

This course is currently in

beta
. Your feedback helps us improve! If you're stuck or confused, let us know and we'll help you out. All comments are public and must follow the Apollo Code of Conduct. Note that comments that have been resolved or addressed may be removed.

You'll need a GitHub account to post below. Don't have one? Post in our Odyssey forum instead.