# How to Build a GraphQL API with Node.js, Express.js, and MongoDB

GraphQL has become a powerful alternative to traditional REST APIs. It provides a flexible and efficient way to interact with data through a single endpoint. In this tutorial, I'll guide you through the process of setting up a GraphQL server using **Node.js**, **Express.js**, and **MongoDB**.

### **Prerequisites**

Before we dive into the code, here’s what you should already know:

* **Node.js**
    
* **Express.js**
    
* **MongoDB**
    

If you’re not familiar with any of these, just make sure they’re installed on your machine and you're ready to go.

### **Step 1: Set Up the Project**

Let’s start by creating a new directory for the project and initializing a Node.js application.

1. **Create a directory** for the project:
    
    ```bash
    mkdir graphql-node-express-mongo
    ```
    
2. **Navigate** into the directory:
    
    ```bash
    cd graphql-node-express-mongo
    ```
    
3. **Initialize the npm project**:
    
    ```bash
    npm init -y
    ```
    

Now we’ll install the dependencies to set up the Express server, connect to MongoDB, and provide GraphQL capabilities:

```bash
npm install express express-graphql graphql mongoose dotenv
```

* **express**: Web framework for Node.js.
    
* **express-graphql**: Middleware to integrate GraphQL with Express.
    
* **graphql**: The core GraphQL library.
    
* **mongoose**: ODM (Object Data Modeling) library for MongoDB.
    
* **dotenv**: Helps load environment variables from a `.env` file.
    

### **Step 2: Setting Up MongoDB**

If you don’t have MongoDB set up yet, here’s what to do:

* For **local MongoDB**, install it and start the MongoDB server.
    
* For **MongoDB Atlas** (cloud), create a free cluster and grab your connection string.
    

Once you have the connection string, create a `.env` file in the root folder and add the MongoDB URI:

```bash
# .env
MONGO_DB_URI = "<Your MongoDB Connection String>"
```

This will ensure your MongoDB credentials are kept secure.

### **Step 3: Create the GraphQL Schema**

Next, we’ll define the GraphQL schema. Create a new file called `schema.js` in the root of your project.

#### Define the MongoDB Schema

Let’s start with a simple **User model** for MongoDB.

```javascript
// models/User.js
const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
  name: String,
  email: String,
});

const User = mongoose.model('User', userSchema);

module.exports = User;
```

#### Define the GraphQL Schema

Now, let’s create the GraphQL schema, including queries and mutations.

```javascript
// schema.js
const { GraphQLObjectType, GraphQLSchema, GraphQLString, GraphQLList } = require('graphql');
const User = require('./models/User');

// Define the GraphQL User Type
const UserType = new GraphQLObjectType({
  name: 'User',
  fields: () => ({
    id: { type: GraphQLString },
    name: { type: GraphQLString },
    email: { type: GraphQLString },
  }),
});

// Root Query to fetch users
const RootQuery = new GraphQLObjectType({
  name: 'RootQueryType',
  fields: {
    users: {
      type: new GraphQLList(UserType),
      resolve(parent, args) {
        return User.find(); // Fetch all users from MongoDB
      },
    },
    user: {
      type: UserType,
      args: { id: { type: GraphQLString } },
      resolve(parent, args) {
        return User.findById(args.id); // Fetch a user by ID
      },
    },
  },
});

// Mutation to add a new user
const Mutation = new GraphQLObjectType({
  name: 'Mutation',
  fields: {
    addUser: {
      type: UserType,
      args: {
        name: { type: GraphQLString },
        email: { type: GraphQLString },
      },
      resolve(parent, args) {
        const user = new User({
          name: args.name,
          email: args.email,
        });
        return user.save(); // Save the new user to MongoDB
      },
    },
  },
});

// Create the GraphQL Schema
const schema = new GraphQLSchema({
  query: RootQuery,
  mutation: Mutation,
});

module.exports = schema;
```

### **Step 4: Set Up the Express Server**

Now, let’s wire everything up by setting up the **Express server** and **GraphQL middleware**. Create a file called `server.js` in your project’s root folder.

```javascript
// server.js
const express = require('express');
const mongoose = require('mongoose');
const { graphqlHTTP } = require('express-graphql');
const dotenv = require('dotenv');
const schema = require('./schema');

// Load environment variables from the .env file
dotenv.config();

const app = express();

// Connect to MongoDB
mongoose.connect(process.env.MONGO_DB_URI, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
})
  .then(() => console.log('MongoDB connected'))
  .catch(err => console.log(err));

// Set up the GraphQL endpoint
app.use('/graphql', graphqlHTTP({
  schema,
  graphiql: true, // Enable GraphiQL for testing queries
}));

// Start the server
app.listen(4000, () => {
  console.log('Server running on http://localhost:4000/graphql');
});
```

### **Step 5: Testing the GraphQL API**

Once your server is running, open [`http://localhost:4000/graphql`](http://localhost:4000/graphql) in your browser. You should see **GraphiQL**, a web-based IDE for testing GraphQL queries.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1737282978495/7d5a6dd0-0855-4eac-a268-a20ff0063f71.png align="center")

#### Test Query: Fetch All Users

To fetch all users, enter this query in the GraphiQL interface:

```graphql
{
  users {
    name
    email
  }
}
```

#### Test Mutation: Add a New User

To add a new user, run this mutation:

```graphql
mutation {
  addUser(name: "Jane Doe", email: "jane.doe@example.com") {
    name
    email
  }
}
```

You should see the newly added user in the response.

### **Step 6: Conclusion**

Congratulations! You’ve successfully built a GraphQL API with **Node.js**, **Express.js**, and **MongoDB**. In this tutorial, you’ve learned how to:

* Set up a **MongoDB** connection.
    
* Create **GraphQL queries** and **mutations**.
    
* Set up an **Express server** to serve your GraphQL API.
    

This is just the beginning. You can now expand your API by adding authentication, pagination, or more complex queries and mutations.

### **Next Steps:**

* Implement **authentication** (e.g., using JWT tokens).
    
* Add **pagination** for handling large data sets.
    
* Deploy your application to services like **Vercel** or **AWS** for production.
