DEV Community

Cover image for Understanding Schema and Types in GraphQL
Bhavesh Yadav
Bhavesh Yadav

Posted on

Understanding Schema and Types in GraphQL

Welcome to the second part of our GraphQL series! In the first part, we explored an introduction to GraphQL, discussing its advantages over REST and diving into the basics of GraphQL syntax and structure. If you missed it, you can catch up on the first part [link to the first part of the series].

In this blog post, we will deep dive into the concepts of schema and types in GraphQL. These are crucial components of GraphQL that allow us to define the structure of our data and shape our API in a predictable and efficient manner.


Introduction to Schema in GraphQL

In GraphQL, a schema plays a crucial role in defining the capabilities and structure of your API. It serves as a contract between the server (GraphQL backend) and the client (GraphQL consumer). The schema specifies the types of data that can be requested from the API and the operations that can be performed on that data.

A GraphQL schema is essentially a collection of GraphQL types. These types define the shape and structure of data available in the API. The two primary types in a GraphQL schema are Object Types and Scalar Types.

To define a schema in GraphQL, you typically use the GraphQL Schema Definition Language (SDL). SDL provides a concise syntax for defining types, fields, and relationships between types. It allows you to specify object types, fields, arguments, input types, and more.

In addition to Object Types and Scalar Types, a GraphQL schema may also include interfaces, unions, enumerations, and directives. Interfaces define a contract for objects to implement a specific set of fields. Unions allow a field to return multiple types. Enumerations define a specific set of allowed values for a field. Directives provide a way to describe additional instructions or metadata about certain fields or operations.

The schema is a fundamental aspect of a GraphQL API. By defining a clear and well-structured schema, you enable clients to understand and interact with your API effectively. Clients can query for the specific data they need, avoiding over-fetching or under-fetching of data.


Understanding Types in GraphQL

Types are a crucial concept in GraphQL as they define the shape of the data and allow you to express the structure of your API. GraphQL has several built-in scalar types, and you can also define your custom types.

1. Scalar Types

Scalar types represent primitive data types in GraphQL. They are the leaf nodes of your graph and hold a single value. GraphQL comes with five built-in scalar types:

  • String: represents a sequence of characters.
  • Int: represents a signed 32-bit integer value.
  • Float: represents a signed double-precision floating-point value.
  • Boolean: represents a logical value (true or false).
  • ID: represents a unique identifier, often used as a unique key to fetch an object or as a reference in a cache.

2. Object Types:

Object types are the most common types in GraphQL. They represent the entities or objects in your data model. An object type has fields, which are properties or attributes of the object. Each field has a name and a specific type, which can be a scalar type or another object type. For example, you might have an "Author" object type with fields like "name" (String), "age" (Int), and "books" (a list of "Book" object type).

3. Lists and Non-null

In GraphQL, you can define fields as lists or non-null. A list represents an array-like structure that holds multiple values. For instance, if a field is defined as [String], it represents a list of strings. Non-null types, denoted by an exclamation mark (!), indicate that a field must always have a non-null value. For example, if a field is defined as String!, it means that the field will always return a non-null string value.

4. Enums

Enums (Enumerations) allow you to define a specific set of allowed values for a field. You can think of enums as a finite collection of predefined values. For example, you could have an enum type called "Status" with possible values like "ACTIVE," "INACTIVE," and "PENDING."

5. Interfaces and Unions

Interfaces and unions help to define shared fields and relationships between different types. An interface is an abstract type that defines a set of fields that a type must implement. It allows you to enforce common fields and ensure consistency across various object types. On the other hand, a union represents a type that can be one of several possible object types. It provides flexibility when a field could return different types of objects.

GraphQL also supports input types, which allow you to pass complex arguments to mutations or queries.

Remember, the schema serves as the contract that defines all the types and relationships in your GraphQL API. By defining clear and well-structured types, you provide a consistent and predictable API for clients to interact with.


Fields and Arguments in GraphQL

Fields

Fields are the fundamental building blocks of a GraphQL query. They represent the specific pieces of information you want to retrieve from the server. Each field has a name and a return type, which can be a scalar type, an object type, or a list of either.

For example, consider a GraphQL query to fetch information about a user:

query {
  user {
    id
    name
    email
    createdAt
  }
}
Enter fullscreen mode Exit fullscreen mode

In this query, "id," "name," "email," and "createdAt" are fields that represent the specific data you want to retrieve for the "user" object.

Arguments

Arguments in GraphQL allow you to pass parameters to fields and provide additional constraints or filters to customize the behavior of the server's response.

Here's an example of a GraphQL query with arguments:

query {
  userById(id: "123") {
    name
    email
  }
}
Enter fullscreen mode Exit fullscreen mode

In this query, "id" is an argument passed to the "userById" field, specifying that you want to retrieve the user with the ID "123." The server can then use this argument to query the data source and return the corresponding user's "name" and "email" fields.

Arguments can have different types, such as scalars or input types, depending on how they are defined in the schema.

Here's another example that demonstrates passing multiple arguments to a field:

query {
  booksByAuthor(authorId: "456", limit: 10) {
    title
    publishedDate
  }
}
Enter fullscreen mode Exit fullscreen mode

In this query, "authorId" and "limit" are arguments passed to the "booksByAuthor" field. The argument "authorId" specifies the author's ID, and "limit" restricts the number of books returned to 10.

By using arguments, you can dynamically control the data retrieval and tailor the server's response to your specific needs.

It's important to consult the API documentation or schema for available fields and their corresponding arguments to construct valid GraphQL queries.


Simple GraphQL Server Example with Express and GraphiQL Interface

Here's a complete example of a basic GraphQL setup with an explanation of each component:

  • Start by installing the necessary dependencies:
npm install graphql express express-graphql
Enter fullscreen mode Exit fullscreen mode
  • Create a file named server.js and add the following code:
const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { buildSchema } = require('graphql');

// Define the schema
const schema = buildSchema(`
  type Query {
    hello: String
  }
`);

// Define the root resolver
const root = {
  hello: () => 'Hello, GraphQL!'
};

// Create an Express server
const app = express();

// Set up the GraphQL endpoint
app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true
}));

// Start the server
app.listen(4000, () => {
  console.log('Server running at http://localhost:4000/graphql');
});
Enter fullscreen mode Exit fullscreen mode
  • Save the file and run the server using the command:
node server.js
Enter fullscreen mode Exit fullscreen mode
  • Now, if you navigate to http://localhost:4000/graphql in your browser, you should see the GraphiQL interface.

  • On the left side of the GraphiQL interface, enter the query:

query {
  hello
}
Enter fullscreen mode Exit fullscreen mode
  • Click the "Play" button (or press Ctrl + Enter), and you will see the result on the right side of the interface:
{
  "data": {
    "hello": "Hello, GraphQL!"
  }
}
Enter fullscreen mode Exit fullscreen mode

Now you have a working GraphQL server! Let's break down the code:

  • First, we import the required dependencies: express, express-graphql, and buildSchema from graphql.
  • We define the GraphQL schema using the buildSchema function. In our example, we have a single query named hello, which returns a String.
  • We create a root resolver object that defines how the hello query should be resolved. In this case, it simply returns the string 'Hello, GraphQL!'.
  • We set up an Express server, create a GraphQL middleware, and attach it using app.use.
  • The middleware is configured with the schema, root resolver, and the option graphiql: true, which enables the GraphiQL interface.
  • Finally, we start the Express server on port 4000 and log a message to the console.

That's the basic structure of a GraphQL server, and you can expand upon it by adding more types, queries, mutations, and resolvers as needed.


Conclusion

In this blog post, we delved into the core concepts of schema and types in GraphQL. We explored the importance of schemas in defining the contract between the server and client, and how types and fields shape the structure of our GraphQL API.

With this knowledge, you now have the foundation to create powerful and efficient APIs using GraphQL. In the next part of our series, we will explore mutations and how they enable data manipulation in GraphQL.

Stay tuned for the third part of the series.

If you have any questions, feel free to comment.

Happy Coding! 😄🚀


Hey there! I'm Bhavesh, an avid tech enthusiast and blogger. As a curious explorer of the latest technological trends, I love sharing my knowledge through informative tutorials and captivating tech blogs. Feel free to contact me anytime—I'm always ready to help! You can catch me on Twitter here for exciting tech updates and engaging discussions. Need to get in touch? Shoot me an email at bhaveshy737@gmail.com. Let's embark on this tech journey together and stay connected across my social media platforms for thrilling tech content! 😊📱🌐

Top comments (1)

Collapse
 
dsaga profile image
Dusan Petkovic

Great write up, really easy to understand, really interested in building something more involved with graphql, I am just wondering what is the best way to think while designing a graphql schema, as I am more used to designing REST API's