Routing Controllers with MongoDB tutorial

Table of contents

This is a guide to setting up Routing Controllers (a very simple npm package to run an express server) with MongoDB.

I have a guide on setting up routing-controllers from scratch here.

So if you are following along, make sure to run through that first to set up the initial routing-controllers server.

This page will now focus on what you need to do to run a mongodb server in your routing-controllers app.

Where to get an instance of MongoDB

For easy development I would recommend first trying out railway.app. I'm in no way sponsored by them... they just have a great interface to instantly deploy a small mongodb server (for free).

Some shortcuts I'm taking for this tutorial

This is a basic tutorial showing how to set up MongoDB in a routing-controllers app. I'm going to skip anything like DI (Dependency injection), and just use a very basic mongoose setup.

I'm also going to put all of the schemas in one file, and re-use our existing controller. I also won't use good RESTful examples. But this should make this easy to copy/paste and you can refine it into something more production ready!

I'm also going to hard code in the mongodb connection string. do not do this in a real app! use environment variables.

Install mongoose

Assuming you already have routing-controllers, express, etc set up then all you will need to do is install mongoose:

yarn add mongoose

Now let's create a schema for our MongoDB collections....

Create a file in ./src/schemas.ts

(for a real app: don't put them all in this file!)

And paste in this code, which uses mongoose to set up a schema for a blog post object:

import mongoose from "mongoose";

const BlogPostSchema = new mongoose.Schema({
    title: {
        type: String,
        required: true,
    },
    views: {
        type: Number,
        required: true,
    },
    isPromoted: {
        type: Boolean,
        required: false,
        default: false,
    },
    body: {
        type: String,
        required: true,
    },
});

export const BlogPost = mongoose.model("BlogPost", BlogPostSchema);

Connect to a mongodb database

Create a file ./src/database.ts and add this function to connect to mongodb via mongoose:

const mongoose = require("mongoose");

export const connectToDatabase = async () => {
    try {
        console.log("Connecting to db");
        // get this url from railway.app - copy the full url with username/password.
        // DO NOT DO THIS IN A PRODUCTION APP
        // USE ENVIRONMENT VARIABLES AND DO NOT COMMIT THE PASSWORD TO YOUR GIT REPO...
        await mongoose.connect(
            "mongodb://mongo:YOUR_USERNAME@YOUR_HOSTNAME" // FOR DEVELOPMENT ONLY!
        );
        console.log("Connected to db")
    } catch (error) {
        console.error(error);
        process.exit(1);
    }
};

And in your server.ts, add this:

// src/server.ts
import { createExpressServer } from 'routing-controllers';
import {HelloWorldController} from './controllers/HelloWorldController';
import {connectToDatabase} from "./database"; // << import this

const PORT = 4000;

async function start() {
    console.info(`Starting server on http://localhost:${PORT}`);

    const routes = [HelloWorldController];

    await connectToDatabase() // <<< add this

    const app = createExpressServer(
        {
            controllers: routes,
        }
    );

    app.listen(PORT);

}

start();

Now use the mongodb data in your controller

I'm going to reuse the existing hello-world controller.

// HelloWorldController.ts
import {Controller, Get, Param, QueryParam} from 'routing-controllers';

import 'reflect-metadata';
import {BlogPost} from "../schemas";

@Controller('/hello-world')
export class HelloWorldController {
    @Get('/posts')
    async posts() {
        const allPosts = await BlogPost.find();

        return {data: JSON.stringify(allPosts)}
    }

    // for tutorial, adding this on a GET request
    // but of course you would want this on a POST request, behind auth!
    @Get('/new-post')
    async newPost() {

        const newRandomPost = new BlogPost({
            title: "A new post added on " + new Date(),
            body: "Some blog post content here " + Math.random(),
            views: 0,
            isPromoted: Math.random() < 0.5
        })
        const insertedPost = await newRandomPost.save();

        return JSON.stringify(insertedPost)
    }

    // again for tutorial this is not following good RESTul urls!
    @Get('/single-post/:id')
    async singlePost(@Param('id') postId: string) {
        const allPosts = await BlogPost.findById(postId);

        return {data: JSON.stringify(allPosts)}
    }

    @Get('/index-html')
    async indexHtml() {
        const allPosts = await BlogPost.find();
        const html = allPosts.map(post => `<div>
            <h1>${post.title}</h1>
            <a href='/hello-world/single-post-html/${post.id}'>link</a>
        </div>`)
        return html.join("\n");
    }

    @Get('/single-post-html/:id')
    async singlePostHtml(@Param('id') postId: string) {
        const post = await BlogPost.findById(postId);
        const html = [
            `<h1>${post.title}</h1>`,
            `<div>${post.body}</div>`,
            `<div>Views: ${post.views}</div>`,
        ]
        return html.join("\n");
    }
}

(make sure you are still including this controller in your routing-controllers server set up (within your createExpressServer call - see my previous tutorial for info)

Now visit your server

Visit http://localhost:4000/hello-world/posts and you should see the empty array.

Visit http://localhost:4000/hello-world/new-post and it will generate and save a new dummy post.

Visit http://localhost:4000/index-html to see a list of your posts, with a clickable link

Next steps

This is a short introduction to set up routing controllers with MongoDB - but for a real app you will want to clean it up and organise your schemas/connection better.

These are some of the steps I'd do next but are out of scope of this tutorial.

Comments Routing Controllers with MongoDB tutorial