Write Crud Functionality With GraphQL & MongoDB in Expressjs — Part 3

Nutan
9 min readDec 3, 2020

--

Create expressjs project — part 1

We have already created a expressjs project. We are going to use same project for further steps. If you don’t have, you can go through below link.

Create GraphQL API in Expressjs Project Using Apollo Server Express

Install MongoDB and connect to database — part 2

If you have not connected to MongoDB in your project. You can go through below link:

Connect to MongoDB in Express Project — Part 2

Let us start, first move schema and resolvers to separate files

Already we have created “Hello World” GraphQl api. Let us move query and resolvers in separate files.

Create schema.js file

Create schema.js file in src folder. Write following code in src/schema.js file.

//file: src/schema.js
const { gql } = require('apollo-server-express');

module.exports = gql`
type Query {
hello: String
}
`;

Create resolvers folder inside src folder. In that resolvers folder create query.js and index.js file .

Write the following code in src/resolvers/query.js

//file: src/resolvers/query.js
module.exports = {
hello: () => 'Hello world!'
}

Write the following code in src/resolvers/index.js

//file: src/resolvers/index.js
const Query = require('./query');
module.exports = {
Query
};

Modify src/index.js file

Remove gql from below line. Because we have moved gql to src/schema.js file.

const { ApolloServer } = require('apollo-server-express');

Include schema and resolvers like below:

// GraphQL's schema ‘Query’
const typeDefs = require('./schema');
// create resolver functions for Query schema
const resolvers = require('./resolvers');

Updated src/index.js

//file: src/index.js//include express module or package
const express = require('express');
const { ApolloServer } = require('apollo-server-express');
const db = require('./db');
require('dotenv').config()const port = process.env.PORT// GraphQL's schema ‘Query’
const typeDefs = require('./schema');
// create resolver functions for Query schema
const resolvers = require('./resolvers');
//create instance of express
const app = express();
// Connect to the database
const MONGO_HOSTNAME = process.env.MONGO_HOSTNAME;
const MONGO_PORT = process.env.MONGO_PORT;
const MONGO_DB = process.env.MONGO_DB;
const DB_URL = `mongodb://${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_DB}`db.connect(DB_URL);
// create an instance of Apollo Server
const server = new ApolloServer({ typeDefs, resolvers });
// Apply the Apollo GraphQL middleware and set the path to /api
server.applyMiddleware({ app, path: '/api' });
app.get('/', (req, res) => res.send('Hello World'));
app.listen({ port }, () =>
console.log(
`Server running at http://localhost:${port}`
)
);

Run the application

Open command prompt, go to project folder and run the project.

F:
cd F:\javascript-projects\express-projects\gqlapi
npm run dev

Browse http://localhost:4000/api

Write query in GraphQL playground

query {
hello
}

Output should get like previously

We have only moved code in separate files.

Let us start defining our model

Mongoose models provide several static helper functions for CRUD operations. Each of these functions returns a mongoose Query object.

Define model/schema

We have created library database in previous tutorial. We will create crud functionality for book. So we will create book schema/model.

Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.

We are creating a book schema and it’s fields are title, author and timestamps. The next step is compiling our schema into a Model.

Fields or properties are:

id: Id will be generated automatically.

title: Data type of title is String and it is required field.

author: Data type of author is String and it is also required field.

timestamps: The timestamps option tells mongoose to assign createdAt and updatedAt fields to your schema. The type assigned is Date.

Create a folder called models inside src folder. Then create book.js and index.js file inside src/models folder.

Write the following code in src/models/book.js file

//file: src/models/book.js
// Require the mongoose library
const mongoose = require('mongoose');
// Define the book schema
const bookSchema = new mongoose.Schema(
{
title: {
type: String,
required: true
},
author: {
type: String,
required: true
}
},
{
timestamps: true
}
);
const Book = mongoose.model('Book', bookSchema);module.exports = Book;

Write the following code in src/models/index.js fie

//file: src/models/index.js
const Book = require('./book');
const models = {
Book
};
module.exports = models;

Get list of books from database

Declare GraphQL schema

We are creating GraphQL schema, which is Book object and it’s fields are id, title and author. And their types are ID, String and String.

Next we are defining Query type books, which will return list of Book.

Write the following code in src/schema.js.

// file: src/schema.js
const { gql } = require('apollo-server-express');
module.exports = gql`
type Book {
id: ID!
title: String!
author: String!
}
type Query {
hello: String,
books: [Book!]!,
}
`;

Create resolvers function for Query type books

Model.find() — Finds documents from our database.

Write the following code in src/resolvers/query.js file

//file: src/resolvers/query.js
const models = require('../models')
module.exports = {
hello: () => 'Hello world!',
books: async () => {
return await models.Book.find()
},
}

Modify src/index.js file

Include models in index.js

//file: src/index.js
const models = require('./models');

Modify ApolloServer instance and add context:

//file: src/index.js
// create an instance of Apollo Server
const server = new ApolloServer({
typeDefs,
resolvers,
context: () => {
return { models };
}
});

Update src/index.js file

//file: src/index.js//include express module or package
const express = require('express');
const { ApolloServer } = require('apollo-server-express');
const db = require('./db');
require('dotenv').config()const port = process.env.PORT// GraphQL's schema ‘Query’
const typeDefs = require('./schema');
// create resolver functions for Query schema
const resolvers = require('./resolvers');
//create instance of express
const app = express();
// Connect to the database
const MONGO_HOSTNAME = process.env.MONGO_HOSTNAME;
const MONGO_PORT = process.env.MONGO_PORT;
const MONGO_DB = process.env.MONGO_DB;
const DB_URL = `mongodb://${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_DB}`db.connect(DB_URL);
// create an instance of Apollo Server
const server = new ApolloServer({
typeDefs,
resolvers,
context: () => {
return { models };
}
});
// Apply the Apollo GraphQL middleware and set the path to /api
server.applyMiddleware({ app, path: '/api' });
app.get('/', (req, res) => res.send('Hello World'));
app.listen({ port }, () =>
console.log(
`Server running at http://localhost:${port}`
)
);

Run the application

npm run dev

Browse url http://localhost:4000/api and write query in GraphQL playground like below:

query {
books {
id
title
author
}
}

Output will show like below:

{
"data": {
"books": []
}
}

We can see there is no record of book so it is showing empty list.

Add/Create new book

Add Mutation GraphQL schema type in src/schema.js file

The Mutation type is similar in structure and purpose to the Query type. Whereas the Query type defines entry points for read operations, the Mutation type defines entry points for write operations.

The addBook mutation accepts two arguments (title and author) and returns a newly created Book object.

//file: src/schema.js
type Mutation {
addBook(title: String!, author: String!): Book!
}

Create mutation.js file inside src/resolvers folder

Write following code in mutation.js file. This will add Book to the database.

Model.create() — Saves one or more documents to the database.

//file: src/resolvers/mutation.jsconst models = require('../models')module.exports = {
addBook: async (parent, args, { models }) => {
return await models.Book.create({
title: args.title,
author: args.author
});
}
}

Update src/resolvers/index.js file

Include mutation.js file and export Mutation module.

//file src/resolvers/index.js file
const Query = require('./query');
const Mutation = require('./mutation');
module.exports = {
Query,
Mutation
};

Let us add new book, Browse url http://localhost:4000/api

Open new tab and write mutation like below in GraphQL playground

mutation {
addBook (title: "This is a sample javascript book", author: "John Methew") {
title
author
id
}
}

Output should get like below:

{
"data": {
"addBook": {
"title": "This is a sample javascript book",
"author": "John Methew",
"id": "5fc0c5078f78911a7071254d"
}
}
}

One record added in our database. Now we will again see list of books, this time it will show newly added record.

Go to previous tab and execute again same query. This time you will get one record, not empty list.

Find book by id

Write query book with input parameter id and it will return Book

//file: src/schema.js filebook(id: ID!): Book!

Get book by id from database

Model.findById() — Finds a single document by its _id field.

Write following code in src/resolvers/query.js file

//file: src/resolvers/query.js file
book: async (parent, args) => {
return await models.Book.findById(args.id);
}

Browse url http://localhost:4000/api and write query in GraphQL playground

query {
book(id: "5fc0c5078f78911a7071254d") {
id
title
author
}
}

Output should get like below:

{
"data": {
"book": {
"id": "5fc0c5078f78911a7071254d",
"title": "This is a sample javascript book",
"author": "John Methew"
}
}
}

Update record

Write updateBook mutation GraphQL schema in src/schema.js file

//file: src/schema.js
updateBook(id: ID!, title: String!, author: String!): Book!

Find record by id and update in src/resolvers/mutation.js

Model.findByIdAndUpdate(): Mongodb finds a matching document, updates it according to the update arg, passing any options, and returns the found document (if any) to the callback. The query executes if callback is passed.

//file: src/resolvers/mutation.jsupdateBook: async (parent, { id, title, author }, { models }) => {
return await models.Book.findOneAndUpdate(
{
_id: id,
},
{
$set: {
title,
author
}
},
{
new: true
}
);
}

Browse url http://localhost:4000/api and update record

Open new tab in GraphQL playground and write mutation like below.

mutation {
updateBook(
id: "5fc0c5078f78911a7071254d",
title: "This is updated title of javascript book",
author: "Junior John Methew"
){
id
title
author
}
}

Output should get like below:

{
"data": {
"updateBook": {
"id": "5fc0c5078f78911a7071254d",
"title": "This is updated title of javascript book",
"author": "Junior John Methew"
}
}
}

Delete record

Write deleteBook mutation GraphQL schema in src/schema.js file

//file: src/schema.js
deleteBook(id: ID!): Boolean!

Delete record from database in src/resolvers/mutation.js file

Model.findOneAndRemove(): Mongodb finds a matching document, removes it, passing the found document (if any) to the callback.

//file: src/resolvers/mutation.js
deleteBook: async (parent, { id }, { models }) => {
try {
await models.Book.findOneAndRemove({ _id: id});
return true;
} catch (err) {
return false;
}
},

Browse url http://localhost:4000/api and delete record

Open new tab in GraphQL playground and write mutation like below:

mutation {
deleteBook(id: "5fc0c5078f78911a7071254d")
}

Output should get like below:

{
"data": {
"deleteBook": true
}
}

Record deleted successfully. Now if we will see below query in GraphQL playground, it will return empty array, because there is no record now.

query {
books {
id
title
author
}
}

Output:
{
"data": {
"books": []
}
}

--

--

Nutan

knowledge of Machine Learning, React Native, React, Python, Java, SpringBoot, Django, Flask, Wordpress. Never stop learning because life never stops teaching.