Create a GraphQL Schema and Resolver for Querying

In this blog, I will discuss about GraphQL, it’s schema creation, how to use resolvers and how to use query by passing arguments. Lets first understand what is GraphQL. 
GraphQL is a query language for your API and a server-side runtime
for executing queries by using a type system you define for your data.
GraphQL isn’t tied to any specific database or storage engine and is instead backed by your existing code and data. So I used MongoDB as my database. A GraphQL service is created by defining types and fields on those types.For example, if I want to create an user api so I will define a type by name “User” and add fields that are related to the User type. 
        IN JAVASCRIPT
Below I created a UserType.js file

[cc lang=”javascript”]
const graphql = require(‘graphql’);
exports = module.exports = new graphql.GraphQLObjectType({
name: ‘User’,
description: ‘Describes an user’,
fields: () => ({
name : {
type: graphql.GraphQLString
},
email: {
type: graphql.GraphQLString
},
language: {
type: graphql.GraphQLString,
},
password: {
type: graphql.GraphQLString
},
mobile: {
type: graphql.GraphQLString
}
})
});
[/cc]

 Lets walk through the above UserType.js File in following steps. 
Here at line-1 I used a graphql module. I installed it using npm.At line-2 I 
used export to export the whole User Type. We always need to create a GraphQL 
Object while creating a schema. So, I created a new GraphQLObject that 
would contain my schema ofUserType. At line-3 I assign a name to my schema.
Remember thatevery schema should always have a unique  name.At line-4 it 
gives a basic description of the user type. At line-5 I assigned fields to 
User type. A function is created and is getting all user fields in return.
Each field is assigned by a field name and its type. GraphQL provides 
various data types.
Now, we know how to create a  simple schema. I will discuss some advance things about  schema in my future blogs.
Lets move further and see how to  create a query, arguments that are passed in the query and how to get the queried information using resolver.
                                  In JAVASCRIPT
                       Below I created a UserQueryField.js

[cc lang=”javascript”]
const graphql = require(‘graphql’);

const UserType = require(‘./UserType’);

const NewUserResolver = require(‘./UserGetResolver’);

module.exports = {
userQuery: {
type: UserType,
description: ‘Fetches a particular user by ID!’,
args: {
id: {
type: new graphql.GraphQLNonNull(graphql.GraphQLString),
description: ‘Id for the user.’
}
},
resolve: NewUserResolver
}
}
[/cc]

Lets walk through the above UserQueryField.js File in following steps. 
Here at line-1 I used a graphql module. At line-3 I require my UserType
from the same directory where I created UserQueryField.js. At line-5 I require
a resolver named "UserGetResolver". I will use this resolver to do my main 
task i.e respond to the graphql query or mutation request.Line-7 is just 
exporting the data contained in the curly braces. Line-8  describes the query.
Line-9 contains type and in this I added UserType. The Type tells that the 
query resolver will return a JSON containing all the User fields.Line-11 
represents the args that we will pass while querying.In Line-17 we call 
the resolver.We normally pass three arguments with the resolver. For example
the above resolver (i.e resolve : NewUserResolver)can also be written like 
resolve : NewUserResolver(parent, args, request) . Here argument-1 i.e 
parent tells about the hierarchy. Argument-2 i.e args contains the arguments
that will be passed while querying. Third argument is the request which 
actually contains the request object when we call a query.

Till here we created a schema and a basic query which take arguments. Now let’s understand how to use resolver.
                              In JAVASCRIPT
                       Below I created a UserGetResolver.js

[cc lang =”javascript”]
const keystone = require(‘keystone’),
UserData = keystone.list(‘User’).model,
mongoose = require(‘mongoose’),
ObjectId = mongoose.Types.ObjectId;

function convertToObjectId(id) {
try {
return ObjectId(id);
} catch (c) {
return null;
}
}

getUserResult = (_id, request, cb) => {
// getting user data of particular id
UserData.findOne({_id: convertToObjectId(_id)}).exec((err, _user) => {
if (err) cb(new Error(‘Id is not valid’));
else if (_user) {
// returning data to the cb
cb(null, _user);
}
else cb(new Error(‘No user for session!’));
});
}

exports = module.exports = (parent, args, request) => ( new Promise((resolve, reject) => { /
getUserResult(args.id, request, (err, results) => {
if (err) return reject(err);
// return fulfill and user data in promise
resolve(results);
})
}
))
[/cc]

Lets walk through the above UserGetResolver.js File in following steps. 
At line-1 I require keystone. KeystoneJS makes it easy to build database-driven
websites, applications and APIs in node.js. Line-2 I linked a user type model 
which store all the fields of user in mongodb. At line-3 & line-4 I used mongoose 
and objectId. This is used to convert a given id into object id because mongodb 
store any id in the form of objectId. At line-16 I used the mongo find query and
passed the id to find the user. So here at line 17 if error comes then I send 
an error as a resolver.As you can see at line-26 a promise is returned. That 
means if an error comes a reject promise with an error is returned and if 
there is no error a resolve promise with the resolved data is returned. At 
line-20  a callback is returned which contains the user data, and the same
data is passed to the resolve promise. We can see the resolve promise in line
30.
Now we know everything about graphql i.e from schema to resolver. Lets see some examples to see how graphql query actually works.
Before that lets see one more file which actually integrates all the above files and gives one unique query name.
                              In JAVASCRIPT
                       Below I created a graphql.js

[cc lang =”javascript”]
const keystone = require(‘keystone’),
graphqlExpress = require(‘express-graphql’),
graphql = require(‘graphql’);

const UserQueryField = require(‘./User/query/UserQueryField’)
const MyGraphQLSchema = new graphql.GraphQLSchema({
/**
* Queries (Read only)
* */
query: new graphql.GraphQLObjectType({
name: ‘Query’,
description: ‘The root of all queries’,
fields: () => ({
user: UserQueryField.userQuery
}),
}),
});
exports.get = graphqlExpress({
schema: LiveBizGraphQLSchema,
graphiql:true
});
[/cc]

At line-6 I created the main schema which contains the parent query. This means that we added all the queries in the root query. Rest is the same as discussed above.
Let’s now check some examples.
The object below is user data stored in mongodb.

{ 
"_id" : ObjectId("59a4009128834251d5107a28"),
 "updatedBy" : ObjectId("59a3ff6428834251d5107a24"),
 "updatedAt" : ISODate("2017-08-30T12:11:12.713Z"),
 "createdBy" : ObjectId("59a3ff6428834251d5107a24"),
 "createdAt" : ISODate("2017-08-28T11:37:54.040Z"),
 "password" : "$2a$10$ulh2E15PLUdEfpb82ApbEOFUPtMjFo5MYS38.MuwKERLbunylJcpe",
 "name" : {
 "last" : "Singh",
 "first" : "Amanpreet"
 },
 "email" : "amanpreet@codalien.com"
}

I will discuss about mutation in Graphql in my next blog. If you have any doubt or find some mistake please tell me in comments. Thanks.

Posted

in

by

Tags:

Comments

2 responses to “Create a GraphQL Schema and Resolver for Querying”

  1. It’s hard to come by well-informed people in this particular subject, however,
    you seem like you know what you’re talking about!
    Thanks

  2. Your point of view caught my eye and was very interesting. Thanks. I have a question for you.

Recent Post

  • What is Knowledge Distillation? Simplifying Complex Models for Faster Inference

    As AI models grow increasingly complex, deploying them in real-time applications becomes challenging due to their computational demands. Knowledge Distillation (KD) offers a solution by transferring knowledge from a large, complex model (the “teacher”) to a smaller, more efficient model (the “student”). This technique allows for significant reductions in model size and computational load without […]

  • Priority Queue in Data Structures: Characteristics, Types, and C Implementation Guide

    In the realm of data structures, a priority queue stands as an advanced extension of the conventional queue. It is an abstract data type that holds a collection of items, each with an associated priority. Unlike a regular queue that dequeues elements in the order of their insertion (following the first-in, first-out principle), a priority […]

  • SRE vs. DevOps: Key Differences and How They Work Together

    In the evolving landscape of software development, businesses are increasingly focusing on speed, reliability, and efficiency. Two methodologies, Site Reliability Engineering (SRE) and DevOps, have gained prominence for their ability to accelerate product releases while improving system stability. While both methodologies share common goals, they differ in focus, responsibilities, and execution. Rather than being seen […]

  • Moving Beyond Traditional Chatbots: Autonomous Agents Redefining Business Operations

    What if your business could operate on autopilot, with AI systems making crucial decisions and managing tasks in real time? Imagine autonomous agents—advanced AI systems capable of making decisions and performing tasks without constant human oversight—transforming your operations. From streamlining workflows to performing seamless customer interactions, these smart agents promise to redefine efficiency and innovation.  […]

  • Mastering Large Action Models: Unleashing Potential and Navigating Complex Challenges in AI

    Imagine an AI assistant that doesn’t just follow commands but anticipates your needs, makes decisions for you, and carries out tasks autonomously. This is the promise of Large Action Models (LAMs), a revolutionary step beyond current AI capabilities. Unlike traditional AI, which reacts to commands, LAMs can think ahead and manage complex scenarios without human […]

  • Harnessing Multimodal AI: A Comprehensive Guide to the Future of Data-Driven Decision Making

    Artificial Intelligence (AI) has been evolving at an astonishing pace, pushing the boundaries of what machines can achieve. Traditionally, AI systems handles single-modal inputs—meaning they could process one type of data at a time, such as text, images, or audio. However, the recent advancements in AI have brought us into the age of multimodal AI, […]

Click to Copy