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.
- Abstract your data fetching to a repository pattern (shown here in PHP, but easy to do in typescript).
- Move all mongodb credentials to environment variables. I'd suggest using
dotenv
npm package. - Also for larger apps I'd suggest using a dependency injection library.
Comments →Routing Controllers with MongoDB tutorial