CRUD Operation Using GraphQL And NodeJS

Introduction

In the previous article, we have discussed the basic concept of GraphQL and the configuration of GraphQL with node js.

Now, in this article, we will create REST APIs using GraphQL + NodeJs and perform CRUD operations to understand the process workflow.

How is CRUD related to GraphQL?

GraphQL splits API requests into Queries and Mutations. A Queries that do not change the state of the data and returns a result only. A Mutations, on the other hand, helps to modify server-side data. So, for CRUD operations, you need to use a query for read operation and a mutation to create, update, or delete operations

The following table shows how CRUD relates to GraphQL.

Introduction - Not a Real DB

It's a "fake" database that allows you to store data in a JSON file. Install NPM package using the below command.

npm i notarealdb || yarn add notarealdb

Official Package: notarealdb

Getting Started

Before starting, Configure the initial project and setup with the help of my earlier article. Once the project is configured we will move forward to perform CRUD operation step by step. Here, will show you CRUD operation with simple user table with Id, FirstName, LastName properties in the fake database.

Step 1

Create user.json file under data folder which we will consider as fake database file. For sample data, I have added below JSON object initially.

[{
    "id": "S1002",
    "firstName": "Developer1",
    "lastName": "Developer1"
}, {
    "id": "S1002",
    "firstName": "Developer2",
    "lastName": "Developer2"
}, {
    "id": "S1003",
    "firstName": "Developer3",
    "lastName": "Developer3"
}]

Step 2

Add schema.graphql file into root directory, this file consists the definition of methods, table property, etc.

type Query {
    greeting: String
    users: [User]
}
type Mutation {
    createUser(firstName: String, lastName: String): User!,
        deleteUser(id: ID!): [User],
        updateUser(id: ID!, firstName: String!, lastName: String!): [User]
}
type User {
    id: ID!firstName: String
    lastName: String
}

Step 3

Add db.js file which configures the route for user where you can export user API route and use in server.js file.

const {
    DataStore
} = require('notarealdb');
const store = new DataStore('./data');
module.exports = {
    users: store.collection('users')
};

Step 4

Create resolvers.js file in root folder. A resolver is a function that defines a value for a type or field in a schema. Resolvers will return Numbers, objects, Strings, Booleans, etc. definitions to connect database or database iterations are done within resolver file.

Read Operation

const {
    DataStore
} = require('notarealdb');
const store = new DataStore('./data');
const Query = {
    users: () => store.collection('users').list(),
}
module.exports = {
    Query
}

Create Operation

const {
    DataStore
} = require('notarealdb');
const store = new DataStore('./data');
const Mutation = {
    // Create new user in user list
    createUser: (root, args, context, info) => {
        let userObj = store.collection('users');
        let idCount = userObj.list().length;
        const newUser = {
            id: `${idCount++}`,
            firstName: args.firstName,
            lastName: args.lastName
        }
        userObj.create(newUser);
        return newUser
    },
}
module.exports = {
    Mutation
}

Update Operation

const {
    DataStore
} = require('notarealdb');
const store = new DataStore('./data');
const Mutation = {
    // Update user detail based on id
    updateUser: (root, args, context, info) => {
        let userList = store.collection('users');
        userList.update({
            id: args.id,
            firstName: args.firstName,
            lastName: args.lastName
        });
        return userList.list()
    },
}
module.exports = {
    Mutation
}

Delete Operation

const {
    DataStore
} = require('notarealdb');
const store = new DataStore('./data');
const Mutation = {
    // Delete specific user from list
    deleteUser: (root, args, context, info) => {
        let userList = store.collection('users');
        userList.delete(args.id);
        return userList.list()
    }
}
module.exports = {
    Mutation
}

Here is what your resolver.js file looks like.

const {
    DataStore
} = require('notarealdb');
const store = new DataStore('./data');
const Query = {
    // Fetch list of user
    users: () => store.collection('users').list(),
}
const Mutation = {
    // Create new user in user list
    createUser: (root, args, context, info) => {
        let userObj = store.collection('users');
        let idCount = userObj.list().length;
        const newUser = {
            id: `${idCount++}`,
            firstName: args.firstName,
            lastName: args.lastName
        }
        userObj.create(newUser);
        return newUser
    },
    // Update user detail based on id
    updateUser: (root, args, context, info) => {
        let userList = store.collection('users');
        userList.update({
            id: args.id,
            firstName: args.firstName,
            lastName: args.lastName
        });
        return userList.list()
    },
    // Delete specific user from list
    deleteUser: (root, args, context, info) => {
        let userList = store.collection('users');
        userList.delete(args.id);
        return userList.list()
    }
}
module.exports = {
    Query,
    Mutation
}

Step 5

Once all files and code are configured, run your project from terminal. Advantage of GraphQL is we can have test playground where we can verify or test implemented APIs. If you want to access GraphQL playground open http://localhost:{your port no}/graphiql. This will open the GraphQL playground. For reference go through below images of playground which helps you to test API

Read Operation

CRUD Operation using GraphQL + NodeJs

Create Operation

CRUD Operation using GraphQL + NodeJs

CRUD Operation using GraphQL + NodeJs

Update Operation

CRUD Operation using GraphQL + NodeJs

Delete Operation

CRUD Operation using GraphQL + NodeJs

Please see the attached source code file for a more detailed understanding.