Welcome to the lesson on "Handling More Complex Data Queries" as part of the "Comprehensive Intro to GraphQL in TypeScript" course. In this lesson, we'll expand on what we learned about mutations in the previous lesson. We'll focus on setting up nested queries in GraphQL to handle more intricate relationships between data, specifically authors and books.
To handle nested queries, we need a schema that represents our data types and their relationships.
-
Define Data Types
We'll create
Author
andBook
types with fields that reference each other:TypeScript1const typeDefs = gql` 2 type Author { 3 id: ID! 4 name: String! 5 books: [Book] 6 } 7 8 type Book { 9 id: ID! 10 title: String! 11 author: Author 12 } 13 14 type Query { 15 books: [Book] 16 authors: [Author] 17 } 18`;
Author
has fieldsid
,name
, andbooks
, which is an array ofBook
.Book
has fieldsid
,title
, and anauthor
, which is of typeAuthor
.
-
Sample Data
Define some sample data to work with:
TypeScript1const authors = [ 2 { id: '1', name: 'J.R.R. Tolkien' }, 3 { id: '2', name: 'J.K. Rowling' } 4]; 5 6const books = [ 7 { id: '1', title: 'The Hobbit', author: '1' }, 8 { id: '2', title: 'Harry Potter', author: '2' } 9];
This data will be used to simulate a small library.
Resolvers are responsible for fetching the data defined in your schema.
-
Define Resolvers
Here's how you can write resolvers to handle nested queries:
TypeScript1const resolvers = { 2 Query: { 3 books: () => books, 4 authors: () => authors 5 }, 6 Book: { 7 author: (book: any) => authors.find(author => author.id === book.author) 8 }, 9 Author: { 10 books: (author: any) => books.filter(book => book.author === author.id) 11 } 12};
- The
Query
resolvers return the sample data forbooks
andauthors
. - The
Book
resolver finds the author of a given book. - The
Author
resolver filters books written by a given author.
- The
-
Initialize Apollo Server
Combine the schema and resolvers to set up the server:
TypeScript1const server = new ApolloServer({ typeDefs, resolvers }); 2 3server.listen().then(({ url }: { url: string }) => { 4 console.log(`🚀 Server ready at ${url}`); 5});
When you run your
server.ts
file, it should print:Plain text1🚀 Server ready at http://localhost:4000/
Now that your server is up and running let's test the nested queries using a real-world example.
-
Define The Query
In a file called
run.ts
, write a query to fetch books and their authors:TypeScript1import fetch from 'node-fetch'; 2 3const fetchBooksAndAuthors = async () => { 4 const query = ` 5 query { 6 books { 7 title 8 author { 9 name 10 } 11 } 12 authors { 13 name 14 books { 15 title 16 } 17 } 18 } 19 `; 20 21 const url = 'http://localhost:4000/'; 22 23 try { 24 const response = await fetch(url, { 25 method: 'POST', 26 headers: { 27 'Content-Type': 'application/json', 28 }, 29 body: JSON.stringify({ query }), 30 }); 31 const data = await response.json(); 32 console.log(JSON.stringify(data, null, 2)); 33 } catch (error) { 34 console.error('Error:', error); 35 } 36}; 37 38fetchBooksAndAuthors();
-
Run The Query
Running this function should give you the following output:
JSON1{ 2 "data": { 3 "books": [ 4 { 5 "title": "The Hobbit", 6 "author": { 7 "name": "J.R.R. Tolkien" 8 } 9 }, 10 { 11 "title": "Harry Potter", 12 "author": { 13 "name": "J.K. Rowling" 14 } 15 } 16 ], 17 "authors": [ 18 { 19 "name": "J.R.R. Tolkien", 20 "books": [ 21 { 22 "title": "The Hobbit" 23 } 24 ] 25 }, 26 { 27 "name": "J.K. Rowling", 28 "books": [ 29 { 30 "title": "Harry Potter" 31 } 32 ] 33 } 34 ] 35 } 36}
This confirms the server correctly handles your nested queries and returns the expected data.
In this lesson, you've learned to handle more complex data queries in GraphQL by setting up nested queries with Apollo Server. You've defined a schema with nested types, implemented resolvers, and tested your queries.
Now, it's time to practice what you've learned. Head over to the practice exercises to solidify your understanding. Try experimenting with more complex queries and relationships to get a deeper grasp of handling data in GraphQL.
Congratulations on making it this far! Keep practicing to reinforce your newfound skills.