
Building a GraphQL API with Node.js, Express, and MongoDB: A Step-by-Step Guide
GraphQL has revolutionized the way developers interact with APIs by making data fetching more efficient and flexible. Pairing GraphQL with Node.js and MongoDB opens up a wide range of possibilities for creating powerful back-end services.
In this tutorial, we will build a simple Employee Management API using Express.js for the server, GraphQL for querying and mutating data, and MongoDB for storing data.
Prerequisites
Before we start, make sure you have the following installed:
- Node.js (v14 or later)
- MongoDB (Ensure MongoDB is running on your local machine or cloud)
- Basic knowledge of JavaScript, Node.js, and GraphQL
Step 1: Setting Up the Project
- Create a new directory for your project:
mkdir graphql-mongodb-project
cd graphql-mongodb-project
2. Initialize the project:
npm init -y
3. Install dependencies: We will need several npm packages to set up our Express.js server, GraphQL API, and MongoDB database.
npm install express express-graphql graphql mongoose nodemon
Step 2: Project Structure
To keep our project organized, we’ll use the following folder structure:
graphql-mongodb-project/
│
├── models/
│ └── Employee.js # Mongoose Model for Employee
│
├── schema/
│ ├── index.js # Root schema for GraphQL queries and mutations
│ └── employee.js # Employee GraphQL schema
│
├── resolvers/
│ └── employeeResolver.js # Resolvers for handling GraphQL operations
│
├── config/
│ └── db.js # MongoDB connection setup
│
├── app.js # Express.js app setup
├── index.js # Main file to start the server
└── package.json # Project dependencies and scripts
Step 3: Defining the MongoDB Model
We’ll use Mongoose to define the schema for our employees in the database. Let’s create the Employee.js
file in the models
directory:
models/Employee.js:
const mongoose = require('mongoose');
const EmployeeSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
age: {
type: Number,
required: true
},
position: {
type: String,
required: true
}
});
module.exports = mongoose.model('Employee', EmployeeSchema);
This schema defines an employee with name
, age
, and position
fields, all of which are required.
Step 4: Creating the GraphQL Schema
Now, let’s define the GraphQL schema for the Employee. This schema will describe the structure of the Employee data and the operations we can perform.
schema/employee.js:
const { GraphQLObjectType, GraphQLID, GraphQLString, GraphQLInt } = require('graphql');
// Employee Type Definition
const EmployeeType = new GraphQLObjectType({
name: 'Employee',
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
age: { type: GraphQLInt },
position: { type: GraphQLString }
})
});
module.exports = EmployeeType;
This defines the EmployeeType, a GraphQL object type that matches the structure of our MongoDB model.
Step 5: Writing Resolvers
Resolvers define how GraphQL queries and mutations fetch or modify the data. Let’s create the resolver for Employee operations in the resolvers
folder.
resolvers/employeeResolver.js:
const Employee = require("../models/Employee");
const EmployeeType = require("../schema/employee");
const {
GraphQLList,
GraphQLID,
GraphQLString,
GraphQLInt,
} = require("graphql");
const getAllEmployees = {
type: new GraphQLList(EmployeeType),
resolve(parent, args) {
return Employee.find();
},
};
const createEmployee = {
type: EmployeeType,
args: {
name: { type: GraphQLString },
age: { type: GraphQLInt },
position: { type: GraphQLString },
},
resolve(parent, args) {
const employee = new Employee({
name: args.name,
age: args.age,
position: args.position,
});
return employee.save();
},
};
const updateEmployee = {
type: EmployeeType,
args: {
id: { type: GraphQLID },
name: { type: GraphQLString },
age: { type: GraphQLInt },
position: { type: GraphQLString },
},
resolve(parent, args) {
return Employee.findByIdAndUpdate(
args.id,
{ name: args.name, age: args.age, position: args.position },
{ new: true }
);
},
};
const deleteEmployee = {
type: EmployeeType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
return Employee.findByIdAndDelete(args.id);
},
};
module.exports = {
getAllEmployees,
createEmployee,
updateEmployee,
deleteEmployee,
};
Step 6: Setting Up the Root Schema
We now need to tie everything together. In schema/index.js
, we'll define the root schema that includes both queries and mutations.
schema/index.js:
const { GraphQLObjectType, GraphQLSchema } = require("graphql");
const {
getAllEmployees,
createEmployee,
updateEmployee,
deleteEmployee,
} = require("../resolvers/employeeResolver");
const RootQuery = new GraphQLObjectType({
name: "RootQueryType",
fields: {
employees: getAllEmployees,
},
});
const Mutation = new GraphQLObjectType({
name: "Mutation",
fields: {
createEmployee,
updateEmployee,
deleteEmployee,
},
});
module.exports = new GraphQLSchema({
query: RootQuery,
mutation: Mutation,
});
Step 7: Connecting MongoDB
Before we can run our application, we need to set up a connection to MongoDB. We’ll do this in config/db.js
.
const mongoose = require("mongoose");
const connectDB = async () => {
try {
await mongoose.connect("mongodb://localhost:27017/employees-app");
console.log("MongoDB Connected");
} catch (error) {
console.error("MongoDB connection failed:", error.message);
process.exit(1);
}
};
module.exports = connectDB;
Step 8: Setting Up the Express Server
Now let’s configure Express to use GraphQL. Create app.js
to set up the server and GraphQL middleware.
const express = require("express");
const { graphqlHTTP } = require("express-graphql");
const schema = require("./schema");
const connectDB = require("./configs/db");
connectDB();
const app = express();
app.use(
"/graphql",
graphqlHTTP({
schema,
graphiql: true,
})
);
module.exports = app;
Step 9: Running the Application
The final step is to create the entry point for our application in index.js
.
const app = require("./app");
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Step 10: Testing the API
- Before running the server, add script code to package.json:
"scripts": {
"dev": "nodemon src/index.js"
},
2. Start the server by running the following command:
npm run dev
3. Access GraphiQL: Open your browser and go to http://localhost:5000/graphql
. You should see the GraphiQL interface, which allows you to test your queries and mutations.
4. Create an Employee: Use the following mutation to create a new employee:
mutation {
createEmployee(name: "Adi Munawar", age: 28, position: "Developer") {
id
name
age
position
}
}
5. Query All Employees: Use this query to fetch all employees:
{
employees {
id
name
age
position
}
}
6. Update an Employee: Use this mutation to update an employee’s data:
mutation {
updateEmployee(id: "EMPLOYEE_ID", name: "John Doe", age: 30, position: "Senior Developer") {
id
name
age
position
}
}
7. Delete an Employee: Use this mutation to delete an employee:
mutation {
deleteEmployee(id: "EMPLOYEE_ID") {
id
}
}
In this tutorial, we built a fully functional GraphQL API with Node.js, Express, and MongoDB. We covered everything from setting up a MongoDB connection to defining GraphQL schemas, queries, mutations, and handling CRUD operations for employees. With this foundational knowledge, you can now extend the API to add more features or work with different data models.
If you want to explore the complete code for this project, you can find it on GitHub:
GitHub Repository: GraphQL Express MongoDB API
Feel free to clone the repository, play around with the code, and customize it to suit your needs!
Happy coding!