Express + TypeScript + Mongo – Part 3 – Mongoose
In the previous articles of this series, we rebuilt the original “ToDo server” application in TypeScript and used Mongo instead of MySQL. In this article, we’ll explore changing the server a bit more by introducing a library called, "Mongoose".
Mongoose introduces some structure to MongoDB applications. It does this by allowing you to create Models and Schemas for your data. In my opinion, it kind of defeats the purpose of even using document stores instead of traditional relational databases, but there might be situations where you need this (for instance, if you’re locked into using Mongo).
Let’s get started with a very basic introduction to Monogoose by installing some new dependencies:
npm install --save mongoose npm install --save-dev @types/mongoose
Next, we’ll create our first model object, “todo.ts” with the following code:
import * as mongoose from "mongoose"; const TodoSchema = new mongoose.Schema({ description: String }); const TodoModel = mongoose.model('Todo', TodoSchema); export { TodoModel }
Here, we’re first creating a Schema object that will define what fields we plan on having in our collection. You can get a bit fancier and add indexes, require fields, custom types, and more, but that’s beyond the scope of this article. After our custom Schema is defined, we create our Model object. The first parameter to the model method is the case-insensitive singular name for your collection. Meaning, our collection name is actually “todos” in Mongo, but here if we specify “todo”, it will automatically append the “s” to the end to make it plural and match our existing collection.
Next, we’ll go to our main.ts file and change the server’s listening event to:
const MONGO_URI = 'mongodb://10.0.0.129:27017/todo'; server.on('listening', async () => { console.info(`Listening on port ${PORT}`); mongoose.connect(MONGO_URI, { useNewUrlParser: true }); mongoose.connection.once('open', () => { console.info('Connected to Mongo via Mongoose'); }); mongoose.connection.on('error', (err) => { console.error('Unable to connect to Mongo via Mongoose', err); }); });
This will let us know when Mongoose has connected to our Mongo server. Note, MONGO_URI now contains the name of our Mongo database.
Finally, we can go to our todo.controller.ts file and rip out the old MongoDB functions in favor of updated ones that use our new model:
import * as express from 'express'; import { TodoModel } from './todo'; const todoRoutes = express.Router(); todoRoutes.get('/todo', async (req: express.Request, resp: express.Response, next: express.NextFunction) => { try { let items: any = await TodoModel.find({}); items = items.map((item) => { return {id: item._id, description: item.description}}); resp.json(items); } catch (err) { resp.status(500); resp.end(); console.error('Caught error', err); } }); todoRoutes.post('/todo', async (req: express.Request, resp: express.Response, next: express.NextFunction) => { const description = req.body['description']; const todo = new TodoModel({description: description}); await todo.save(); resp.end(); }); todoRoutes.put('/todo/:id', async (req: express.Request, resp: express.Response, next: express.NextFunction) => { const description = req.body['description']; const id = req.params['id']; await TodoModel.findByIdAndUpdate(id, {description: description}); resp.end(); }); todoRoutes.delete('/todo/:id', async (req: express.Request, resp: express.Response, next: express.NextFunction) => { const id = req.params['id']; await TodoModel.findByIdAndRemove(id); resp.end(); }); export { todoRoutes }
The nice thing about the Mongoose API is that it’s all promised-base out of the box, so we can easily convert everything over to using async / await to make it look nice.
That’s all that needs to be done in order to switch the project over to using Mongoose. The server should start up as before and all of the data should still be intact.
Overall, I’m not sure what advantage Mongoose + MongoDB gives us over something like MySQL. The only thing I can really see is that if you’re locked into using Mongo already and need to introduce some stricter rules around the data going into Mongo. If that’s the case, then Mongoose is a great fit. If you use Mongoose in your projects or can think of reasons why Mongoose + MongoDB make a great alternative to MySQL / SQL Server / etc, let me (and others) know in the comment section below.
Source code is available here: