Crafting Perfect GraphQL Queries: Techniques and Code Examples for Biginners


GraphQL queries allow clients to fetch specific data from a server in a structured manner. Unlike traditional REST APIs, GraphQL lets you request exactly the data you need, no more and no less. This article introduces basic GraphQL queries and explores nested queries, accompanied by step-by-step explanations.
What Are GraphQL Queries?
In GraphQL, queries are used to retrieve data. A query defines:
What data you need.
How data should be structured in the response.
Example:
Here’s a basic query:
query {
user(id: "1") {
id
name
}
}
This query asks for a user
with the ID "1"
and specifies the id
and name
fields to be returned.
Writing Basic Queries
Step 1: Define the Schema
Create a schema that includes the data structure and fields for your API. Below, we define a User
type and a Query
type:
// schema.graphql
type User {
id: ID!
name: String!
age: Int
}
type Query {
user(id: ID!): User
}
User
Type: Represents a user with fieldsid
,name
, andage
.Query
Type: The root query type defines auser
field that accepts anid
as input and returns aUser
.
Step 2: Implement Resolvers
Create a resolver for the user
query.
func (r *queryResolver) User(ctx context.Context, id string) (*User, error) {
users := map[string]*User{
"1": {ID: "1", Name: "Alice", Age: 25},
"2": {ID: "2", Name: "Bob", Age: 35},
}
user, exists := users[id]
if !exists {
return nil, fmt.Errorf("user not found")
}
return user, nil
}
Explanation:
A
map
is used to simulate a data store.The
id
parameter is used to fetch the corresponding user.If the user is found, it is returned; otherwise, an error is thrown.
Step 3: Query Example
Once the schema and resolver are set up, you can execute a query:
query {
user(id: "1") {
id
name
age
}
}
Output:
{
"data": {
"user": {
"id": "1",
"name": "Alice",
"age": 25
}
}
}
Nested Queries
GraphQL allows you to request related data within a single query. For example, a Post
might be associated with a User
. Nested queries allow clients to fetch both Post
and User
data in one request.
Step 1: Update the Schema
Add a Post
type with a relation to User
.
type Post {
id: ID!
title: String!
author: User!
}
type Query {
post(id: ID!): Post
}
Step 2: Implement Resolvers
Define a resolver for the post
query and include nested user data.
func (r *queryResolver) Post(ctx context.Context, id string) (*Post, error) {
posts := map[string]*Post{
"101": {ID: "101", Title: "GraphQL Basics", Author: &User{ID: "1", Name: "Alice", Age: 25}},
"102": {ID: "102", Title: "Advanced GraphQL", Author: &User{ID: "2", Name: "Bob", Age: 35}},
}
post, exists := posts[id]
if !exists {
return nil, fmt.Errorf("post not found")
}
return post, nil
}
Explanation:
A
map
is used to simulate a collection of posts.Each post includes an
Author
field, which refers to aUser
.
Step 3: Nested Query Example
Fetch a post and its author:
query {
post(id: "101") {
id
title
author {
id
name
}
}
}
Output:
{
"data": {
"post": {
"id": "101",
"title": "GraphQL Basics",
"author": {
"id": "1",
"name": "Alice"
}
}
}
}
Step-by-Step Code Explanation:
Schema Setup: The schema defines the relationships between types, such as a
Post
having anAuthor
.Post Resolver: The
Post
resolver fetches data for thepost
field, including nestedUser
data for theauthor
.Nested Query Execution: The GraphQL query retrieves both the post details and the associated user information in a single request.
Conclusion
In this article, we covered:
Writing basic GraphQL queries to fetch specific data.
Implementing nested queries to retrieve related data in one request.
By using GraphQL’s powerful query language, developers can write efficient and expressive queries tailored to their needs. Start practicing with simple queries and progress to more complex nested queries to unlock the full potential of GraphQL.
Subscribe to my newsletter
Read articles from Shivam Dubey directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
