Easy MongoDB Mongoose Connection with TypeScript Nodejs and Express

Posted January 29, 2024
Easy MongoDB Mongoose Connection with TypeScript Nodejs and Express

Mongoose is primarily created as an ORM for the NoSQL MongoDB database. In this example tutorial, you will learn how to add Mongoose database connections with TypeScript, MongoDB, and Node.js. TypeScript gives your app the advantages of using JavaScript’s advanced features, such as static typing and type checks. This way, Mongoose will inherit TypeScript benefits, and you will try to create a Node.js Express Server to connect and leverage the MongoDB database.

You will learn to add these features to your Mongoose Models/schema and connect to MongoDB with TypeScript Type checks. In summary, you will learn:

  • How to set up a Node.js Express with TypeScript, connect Mongoose and MongoDB example.
  • How to create MongoDB Mongoose Models and connect to your database with TypeScript.
  • Execute a mongoclient with Mongoose to access MongoDB with Express and Typescript.
  • How to use MongoDB Atlas and connect to the database using Mongoose.

Related:Easy TypeORM with Nest.js and MongoDB Example Tutorial

Ready? Dive in and create an Easy MongoDB Mongoose Connection with TypeScript Node.js and Express.

Prerequisites to using Mongoose with TypeScript and Express

Before attempting to connect MongoDB with Mongoose and TypeScript, ensure you have

Setting up TypeScript Node.js APP with Mongoose and Express

We need a Node.js app ready to execute some TypeScript code. This way, we can then use Express to allow Mongoose to connect to MongoDB and perform any operation we want

Go to your working directory and use the following command to get Node.js initialized:

npm init -y

Likewise, it is good to have TypeScript installed globally before attempting to get it ready on Node.js. Use this command:

npm install typescript -g

To allow the application to execute Typescript, initialize Typescript using this command:

npx tsc init

Now you should have package.json and tsconfig.json files ready. This way, TypeScript will work like a charm as we extend to using Mongoose and Express.

To create a Node.js API, you need packages. We are using Mongoose and Express with TypeScript. So the following packages will be good to go:

We will start with dev dependencies. Use the following command with a --save-dev to get them ready:

npm install --save-dev typescript @types/node nodemon ts-node

Now, packages such as Express and Mongoose are core dependencies for implementing the RESTFul aspect of this API. Run the following command to get them ready:

npm i --save express @types/express mongoose @types/mongoose

Note the following two additional dependencies:

  • @types/express
  • @types/mongoose

These packages allow you to access the Typescript safe code associated with each package. Creating an application with Typescript ensures you install the Typescript support of each parent package using the @types annotation, as shown above.

How to Run TypeScript with Mongoose on Node.js

You need a way to run your app. It’s the only way Express executes Mongoose and connects to the MongoDB database.

You’ll add a local command in the scripts tag of the package.json file:

"dev":"nodemon /src/index.ts"

If you prefer to run TypeScript as JavaScript, make sure you have the following lines in your tsconfig.json file:

    "rootDir": "./src", 
    "outDir": "./dist",

This way, you will run Mongoose from the dist directory using the following command:

"start": "node ./src/index.ts",
"dev": "nodemon ./src/index.ts",
"build": "tsc --project tsconfig.json",

Easy MongoDB Mongoose Connection with TypeScript Nodejs and Express

Creating Express Server with Node.js, Typescript and Mongoose

It’s time to start creating the API. First, you must ensure you are in a working directory and create an src directory.

Add an index.ts file and set up a Node.js Typescript server as follows:

  • Import the Mongoose and Express using TypeScript Node.js syntax. At the same time, Initialise express with its instance: (Dont worry about import connectDB from "./config/db.config"; and import todoRouter from './routes/todo.routes', we will create them later)
import "express-async-errors";
import express from "express";
import connectDB from "./config/db.config";
import todoRouter from './routes/todo.routes'

const app = express();
  • Enable support for JSON data in the payload. This step is good when sending requests to or receiving responses from the server. The data will be encoded in JSON format as such:
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
  • Define a port to run the application on. This port will be used to expose the API locally:
const port = process.env.PORT || 5000;
  • Create a TypeScript script to start the Node.js Express server. It should check if Mongoose MongoDB connections are working as well:
app.get('/', (req, res) => {
    res.send("<h1>Todo List using typescript</h1>");
})

// routes
app.use('/api/v1/todos', todoRouter);

const startDB = async () => {
    try {
        await connectDB(process.env.MONGO_URI);
        console.log('Mongodb is connected!!!')
        app.listen(port, () => {
            console.log(`Server is listening on port ${port}...`);
        })
    } catch (error) {
        console.log(error);
    }
}
// connecting to Mongodb and starting the server
startDB();

Connect to MongoDB using TypeScript, Express, and Mongoose

In the src folder, create a config directory and add a db.config.ts file. Let’s craft functions to initiate a connection with the MongoDB database. Please note that the current connection assumes the database starting is from locally installed MongoDB. In case you chose MongoDB cloud, update the connection URL mongodb://localhost:27017/task_app to reflect as such:

Now proceed and define a function for establishing a local connection to the MongoDB database using Mongoose and Typescript:

import mongoose from "mongoose";

const connectDB = (url: any) => {
    mongoose.connect("mongodb://127.0.0.1:27017/task_app");
}

export default connectDB

At this Step: 127.0.0.1 is the same as localhost. Sometimes, localhost fails to connect to MongoDB:

Easy MongoDB Mongoose Connection with TypeScript Nodejs and Express

Note that if you’re using this Mongoose connection with MongoDB Atlas, the above connection string will change as follows:

import mongoose from "mongoose";

const connectDB = (url: any) => {
    mongoose.connect("mongoose.connect('mongodb+srv://userName:[email protected]/', {dbName: 'task_app'})");
}

export default connectDB

At the same time, the URL must match your MongoDB Atlas.

Setting up a TypeScript Express Node.js Todos Model

A Mongoose Model/schema dictates how your databases should look like. In this guide, we’ll use the Todo App to illustrate creating a Node.js Typescript REST API with Mongoose. Your first task is to craft a model.

In Typescript, models define data structure and behavior through classes or interfaces. They ensure a consistent shape, property types, and allowable methods across your application.

For this Todos app, typical properties include title and description. Typescript relies on this model to maintain uniformity throughout the application. This should be the same when using Mongoose.

To start, let’s create a Todos model. In your project src directory, add a models folder and create a todo.models.ts file inside it. In todo.models.ts:

  • Import Schema and model from Mongoose:
import { Schema, model } from 'mongoose';
  • Create a blueprint for Todo with its properties and TypeScript types using the Schema:
// Creating an interface
interface Todos {
    title: string,
    body: string,
    completed: boolean
}

const todoSchema = new Schema<Todos>({
    title: {
        type: String,
        required: [true, "Title should not be empty!"]
    },

    body: {
        type: String,
        required: [true, "Body should not be empty!"]
    },

    completed: {
        type: Boolean,
        default: false
    }
    
}, { timestamps: true});

This sets the Model for the Todo data and serves as a blueprint for the application. To use this Mongoose Schema, define the model and export it:

export const Todo = model<Todos>('Todo', todoSchema);

Using TypeScript Express to Add a Todo to MongoDB with Mongoose

Once you have the connection created and Mongoose adds the Model to the database, let’s dive right away and create some to-dos for the database.

Here, you need to use a POST request and send a JSON payload. Node.js will use Express to create POST routes, allowing Mongoose to connect to MongoDB and save your data.

Create a controllers directory in your src folder and add a todo.controllers.ts file. The controller will host the logic for posting, fetching, deleting, or updating a todo (CRUD)

Let’s now create a method for post data using Typescript. In your todo.controllers.ts, import these packages and modules:

import { Request, Response } from "express";
import { Todo } from "../models/todo.models";
import { StatusCodes } from "http-status-codes";

Create a TodoController class. You will use this class to add methods for fetching all todos, posting, updating, and deleting a task inside this class:

class TodoController {
    // Add CRUDs here
}

export const todoController = new TodoController();

In the todo.controllers.ts file, and ensuring you are inside the TodoController class, create a function for executing POST requests to MongoDB as such:

  // create a todo
  createTodo = async (req: Request, res: Response) => {
    const { title, body } = req.body;

    if (!title || !body) {
      throw new Error("Title and Body must be provided.");
    }

    const newTodo = await Todo.create(req.body);
    res.status(StatusCodes.CREATED).json({ todo: newTodo, msg: "Todo has been created!" });
  };

How to Fetch Data using Mongoose, TypeScript, Express, And MongoDB

Now, let’s create a TypeScript method to retrieve data from the database. Inside the TodoController class, define the following method for fetching tasks:

  // get all todos
  getTodos = async (req: Request, res: Response) => {
    const todos = await Todo.find({}).sort('-createdAt');

    if (todos?.length === 0) {
      throw new Error("Todo list is empty!");
    }

    res.status(StatusCodes.OK).json({ todos, msg: "All Todos have been fetched!" });
  };

  //Get a single todo
  getSingleTodo = async (req: Request, res: Response) => {
    const { id } = req.params;
    const todo = await Todo.findById({ _id: id });

    if (!todo) {
      throw new Error("Requested todo not found!");
    }

    res.status(StatusCodes.OK).json({ todo, msg: "Success" });
  };

Delete and Update Data with Express and MongoDB using Mongoose

To update a task, go to the controllers.ts file. Use findByIdAndUpdate from Mongoose and TypeScript. And inside the TodoController class, define a function for updating a task like this:

  // update todo
  updateTodo = async (req: Request, res: Response) => {
    const { id } = req.params;
    const updatedTodo = await Todo.findByIdAndUpdate({ _id: id }, req.body, { new: true });

    if (!updatedTodo) {
      throw new Error("Requested todo not found!");
    }

    res.status(StatusCodes.OK).json({ todo: updatedTodo, msg: "Todo has been updated" });
  };

Mongoose will use findByIdAndUpdate to target the todo to be updated. If successful, the findByIdAndUpdate method will save the new changes.

To delete a todo, inside the TodoController, add a function for deleting a task and execute findByIdAndDelete from Mongoose:

  // delete todo
  deleteTodo = async (req: Request, res: Response) => {
    const { id } = req.params;
    const deletedTodo = await Todo.findByIdAndDelete({ _id: id });

    if (!deletedTodo) {
      throw new Error("Requested todo not found!");
    }

    res.status(StatusCodes.OK).json({ todo: deletedTodo, msg: "Todo has been deleted" });
  };

Executing Mongoose and Express using Routes

To access all the above methods, you will need some routes that specifically access each method based on its HTTP method and the respective endpoint/route:

To execute the methods, we need to use routes. In the project src folder, create a routes folder and add a todo.routes.ts file to host all your API routes as follows:

import express from "express";
import { todoController } from "../controllers/todo.controllers";

const router = express.Router();

router.route('/').post(todoController.createTodo).get(todoController.getTodos);

router.route('/:id').get(todoController.getSingleTodo).patch(todoController.updateTodo).delete(todoController.deleteTodo);

export default router

Running the Mongoose Connection with TypeScript Nodejs and Express

The app should be ready by run. Use the following command to start it:

npm run dev

Easy MongoDB Mongoose Connection with TypeScript Nodejs and Express

If you have an error like this one:

Easy MongoDB Mongoose Connection with TypeScript Nodejs and Express:

Change localhost in the mongoose.connect("mongodb://localhost:27017/task_app") to 127.0.0.1.

Your TypeScript NodeJS/Express app should be able to use Mongoose and set up your database:

Easy MongoDB Mongoose Connection with TypeScript Nodejs and Express

Testing the Mongoose TypeScript Node.js

This server is running on port 5000 (http://localhost:5000/todos). All requests should point here. Now, let’s test if the API is working as expected.

Let’s first use the POST method to add a new todo as follows:

{
  "title": "Exercise Routine",
  "body": "Follow the workout plan for 30 minutes every day to stay fit and healthy."
}

Easy MongoDB Mongoose Connection with TypeScript Nodejs and Express

POST request changes should reflect your MongoDB database as such:

Easy MongoDB Mongoose Connection with TypeScript Nodejs and Express

Alternatively, send a GET request to http://localhost:5000/todos and fetch the added items:

If you want to update the existing todo, submit a PUT request from Postman to http://localhost:5000/todos/update-note?id=_id_of_post_to_be_updated. Make sure your JSON payload resembles the following format:

Keep in mind that _id_of_post_to_be_updated should be the ID (ObjectId) of the note you wish to update in the MongoDB database:

Use the http://localhost:5000/todos/update-note?id=_id_of_post_to_be_updated endpoint to find single todo or send DELETE requests.

Related: Sequelize Models with Typescript using MySQL and PostgreSQL

Conclusion

You’ve learned:

  • Setting up a Node.js Express with TypeScript, Mongoose, and MongoDB examples.
  • How to create MongoDB Mongoose Models and connect to your database.
  • How to execute a Mongo client with Mongoose to access MongoDB with Express and Typescript.
  • How to use MongoDB Atlas and connect to the database using Mongoose.

Get the whole code on this GitHub Repo.

Happy Coding 🙂👨‍💻🚀!!!

Easy MongoDB Mongoose Connection with TypeScript Nodejs and Express

Written By:

Joseph Chege