Lesson 3
Querying with Arguments in GraphQL
Introduction to Querying with Arguments in GraphQL

In our previous lessons, we've discussed setting up a basic GraphQL server using Apollo Server and creating basic types and queries. In this lesson, we will focus on querying with arguments in GraphQL, which allows you to retrieve specific data based on parameters you provide.

To understand querying with arguments, consider that you might want to fetch details about a specific book from a large collection. Instead of retrieving all books and filtering on the client side, you can pass an argument to your query to get just the book you need directly from the server.

Defining the GraphQL Schema with Arguments

To query specific data, we need to extend our GraphQL schema to include arguments. Recall from previous lessons that the schema defines the types of data and the shape of our queries.

Here’s how we define a schema with arguments:

TypeScript
1import { ApolloServer, gql } from 'apollo-server'; 2 3// Define schema with arguments 4const typeDefs = gql` 5 type Book { 6 id: ID! 7 title: String! 8 author: String! 9 } 10 11 type Query { 12 books: [Book] 13 book(id: ID!): Book 14 } 15`;

In this schema:

  • The Book type has three fields: id, title, and author.
  • The Query type contains two fields:
    • books, which returns an array of Book items.
    • book, which takes an id argument of type ID! and returns a single Book.

Note that the ! symbol in ID!, String!, and other types signifies that these fields are non-nullable. This means that a value for these fields must always be provided and cannot be null. For instance, an id of type ID! must always have a value in any Book object.

Creating Resolvers for Queries with Arguments

Resolvers are functions that return data for the fields defined in your schema. When dealing with arguments, resolvers use these arguments to fetch the specific data requested.

Here are the resolvers for our schema:

TypeScript
1// Sample data 2const books = [ 3 { id: '1', title: 'The Hobbit', author: 'J.R.R. Tolkien' }, 4 { id: '2', title: 'Harry Potter', author: 'J.K. Rowling' }, 5]; 6 7// Resolvers 8const resolvers = { 9 Query: { 10 books: () => books, 11 book: (_: any, args: { id: string }) => books.find(book => book.id === args.id), 12 }, 13};

Explanation:

  • The books resolver returns the entire list of books.
  • The book resolver takes an id argument and returns the book that matches the given id.
Running the Apollo Server with Updated Schema and Resolvers

To see our updated schema and resolvers in action, we need to initialize and start the Apollo Server.

Here’s the code to do just that:

TypeScript
1// Initialize Apollo Server 2const server = new ApolloServer({ typeDefs, resolvers }); 3 4// Start the server 5server.listen().then(({ url }) => { 6 console.log(`🚀 Server ready at ${url}`); 7});

When you run this code in your server.ts file, you should see the following output:

Plain text
1🚀 Server ready at http://localhost:4000/

This indicates that your server is running and ready to handle queries.

Making GraphQL Queries with Arguments

Now, let's make some GraphQL queries that include arguments.

We can use the following code to query all books and a specific book by ID:

TypeScript
1import fetch from 'node-fetch'; 2 3const queryBooks = ` 4 query { 5 books { 6 id 7 title 8 author 9 } 10 } 11`; 12 13const queryBookById = (id: string) => ` 14 query { 15 book(id: "${id}") { 16 id 17 title 18 author 19 } 20 } 21`; 22 23const url = 'http://localhost:4000/'; 24 25async function runQueries() { 26 // Query all books 27 const responseBooks = await fetch(url, { 28 method: 'POST', 29 headers: { 30 'Content-Type': 'application/json', 31 }, 32 body: JSON.stringify({ 33 query: queryBooks, 34 }), 35 }); 36 37 const booksData = await responseBooks.json(); 38 console.log('Books:', JSON.stringify(booksData, null, 2)); 39 40 // Query a book by ID 41 const responseBookById = await fetch(url, { 42 method: 'POST', 43 headers: { 44 'Content-Type': 'application/json', 45 }, 46 body: JSON.stringify({ 47 query: queryBookById('1'), // Replace '1' with the desired book ID 48 }), 49 }); 50 51 const bookByIdData = await responseBookById.json(); 52 console.log('Book by ID:', JSON.stringify(bookByIdData, null, 2)); 53} 54 55runQueries().catch((error) => console.error('Error:', error));

Explanation:

  • We define two GraphQL queries: one to fetch all books and another to fetch a specific book by its ID.
  • We use the fetch function to make HTTP POST requests to our GraphQL server.
  • The server processes the queries and returns the requested data.

Output:

JSON
1Books: { 2 "data": { 3 "books": [ 4 { 5 "id": "1", 6 "title": "The Hobbit", 7 "author": "J.R.R. Tolkien" 8 }, 9 { 10 "id": "2", 11 "title": "Harry Potter", 12 "author": "J.K. Rowling" 13 } 14 ] 15 } 16} 17 18Book by ID: { 19 "data": { 20 "book": { 21 "id": "1", 22 "title": "The Hobbit", 23 "author": "J.R.R. Tolkien" 24 } 25 } 26}
Lesson Summary

In this lesson, we expanded our knowledge of GraphQL by learning how to query with arguments. We:

  • Defined a schema that supports arguments in queries.
  • Created resolvers to handle these queries.
  • Initialized and ran an Apollo Server with the updated schema and resolvers.
  • Made and executed GraphQL queries with arguments.

You should now proceed to the practice exercises to solidify your understanding of querying with arguments. In the next lesson, we will tackle more advanced features to further enhance your skills. Keep practicing and refining your knowledge!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.