Complete Intro Graphql
Fundamentals

GraphQL Fundamentals

To ask any GraphQL server for data, you send it a request written in the GraphQL query language. A GraphQL request is a tree of fields. Let’s explore these two fundamental concepts of the language.

1. Requests

At the core of a GraphQL communication is a request object. The source text of a GraphQL request is often referred to as a document. A document contains text that represents a request through operations like queries, mutations, and subscriptions. It might also contain fragments that are defined and used to compose other operations.

A GraphQL request might also contain an object to represent values of variables that might be used in the request document. The request might also include meta information about the operations. For example, if the request document contains more than one operation, a GraphQL request must include information about which operation to execute. If the request document contains only one operation, the GraphQL server will just execute that. You do not even need to label the operation with a name in that case, but naming operations is a good practice to follow.

ch02 fig 07 gqlia
Figure 6. 1. The structure of a GraphQL request

Let’s look at a full GraphQL request. Here a hypothetical example of that (don’t worry about the new syntax you’ll see here just yet):

Listing 6. 1. Example GraphQL request: Document
query GetEmployees($active: Boolean!) {
  allEmployees(active: $active) {
    ...employeeInfo
  }
}

query FindEmployee {
  employee(id: $employeeId) {
    ..employeeInfo
  }
}

fragment employeeInfo on Employee {
  name
  email
  startDate
}

Since this document uses generic variables (the ones starting with the $ sign), we need a JSON object to represent values specific to a request. For example:

Listing 6. 2. Example GraphQL request: Variables
{
  active: true,
  employeeId: 42
}

Also, since the document contains more than one operation (GetEmployees and FindEmployee), the request needs to provide the desired operation to be executed. For example:

Listing 6. 3. Example GraphQL request: Meta Information
operationName="GetEmployees"

If we send all three elements of this request to a GraphQL server, it will parse the whole document, pick the GetEmployees query, fill the variables values, and return the result of that query.

There are three types of operations that can be used in GraphQL:

  • Query operations that represent a read-only fetch

  • Mutation operations that represent a write followed by a fetch

  • Subscription operations that represent a request for real-time data updates

We will see practical examples of these operation in the next chapter.

The example in listing 5.2 represented a query operation. Here is a hypothetical example of a mutation operation:

Listing 6. 4. Example GraphQL mutation operation
mutation {
  addRating(storyId: 123, rating: 5) {
    story {
      averageRating
    }
  }
}

The mutation operation in listing 6.4 will add a new 5-star rating record for a story and it will then retrieve the new average rating of that same story. Note how this is a write followed by a read. All GraphQL mutation operations follow this concept.

The mutation operation in listing 6.4 did not have a name. An anonymous operation is okay if it is the only operation defined in the document. If the anonymous operation is a query, we can also omit the word "query". This is what we did when we started exploring the GraphiQL editor.

Here is a hypothetical example of a subscription operation:

Listing 6. 5. Example GraphQL subscription operation
subscription StoriesRating {
  allStories {
    id
    averageRating
  }
}

The subscription operation in listing 6.5 will instruct the GraphQL server to open a socket connection with the client, send stories’ IDs along with their average ratings, and keep doing that when that information changes on the server.

2. Fields

One of the core elements in the text of a GraphQL request is the field. The most simplified way to think about a GraphQL request is to think about it as a way to select fields on objects.

A field always appears within a selection set (inside a pair of curly brackets). A selection set is primarily composed of fields.

A field in GraphQL describes one discrete piece of information that you can retrieve about an object. It could be describing a scalar value (like the name of a person or their birth year), or it could describe an object (like the home planet of a Star Wars character), or it could describe a list of objects (like the list of films in which a Star Wars character appeared). For the last two cases, their fields will contain another selection set to customize the information needed about the objects that are described by them.

Here is an example GraphQL query that has examples of different types of fields:

Listing 6. 6. GraphQL fields
{
  me {
    email
    birthday {
      month
      year
    }
    friends {
      name
    }
  }
}

The fields email, month, year, and name are all scalar fields. The fields me and birthday are fields that describe objects, and therefore they needed their own nested selection sets. The field friends describes a list of friend objects and therefore it also needed a nested selection set to represent each object in that list.

All GraphQL operations must specify their selections down to fields which return scalar values. They cannot, for example, have fields that describe objects without providing further nested selection sets to specify which scalar values to fetch for these objects. The last nested level of fields should always consist of only fields that describe scalar values. For the example in listing 6.6, if you do not specify the nested selection set for the field friends (the { name } part), the GraphQL query would not have been valid because not all of the last nested level fields would be describing scalar values in that case.

The top-level fields in an operation usually represent some information that is globally accessible to your application and its current viewer. Some typical examples of these top fields include references to a current logged‐in viewer or fields accessing certain types of data referenced by a unique identifier.

{
  me {
    fullName
  }
}

In this query, the field “me” usually represent the currently logged-in user. Other APIs name this top-level field “viewer” instead.

# Ask for the user whose ID equal to 42
{
  user(id: 42) {
    fullName
  }
}

In this query, the field user represents one of many users in a graph of data. To instruct the server to pick one user, we specify a unique ID value for the user field.

Note how in the previous example the # character was used to write a comment about the query. This is the official character to comment a single line (or remainder of a line) in a GraphQL document. There is no supported way to have multiline comments in GraphQL documents, but you can just have many lines that each start with the # character. The server will just ignore all the comments. It will also ignore any extra spaces, all the line terminators, and all insignificant commas between the fields. All these characters can be used to improve the legibility of source text and emphasize the separation of tokens. They have no significance to the semantic meaning of GraphQL documents.