Node.js API with MongoDB

Nicky Liu
Future Vision
Published in
4 min readSep 1, 2019

My previous article on the basics of Node.js (https://medium.com/future-vision/basics-of-node-js-46bf6e7a1a3b) explained some of the basics of Node.js as well as how it might function as an API.

This article will go more in depth and combine Node.js with MongoDB to make a full-on backend api involving accounts.

1. Create a folder and cd into it.

2. npm init

3. npm install express nodemon

(nodemon makes it so that the changes in the files are automatically detected and the server restarted, so that you don’t have to keep restarting it manually).

4. Inside the file package.json change the line inside of “script” to:

"start": "nodemon app.js"

(this allows you to run the program with “npm start” instead of having to type “nodemon app.js”, not actually that big of a difference)

5. npm install mongoose

(This connects our app with MongoDB

6. mlab.com > make an account > create cluster > follow all steps

7. When connecting select “connect your application” and copy the connection string

8. Back inside your app.js paste:

mongoose.connect("paste-connection-string-here-with-updated-password", {useNewUrlParser: true})

9. Create an api folder.

10. Inside of that create a model folder and a route folder.

11. Create an account.js file inside the model folder.

12. The model will need an id and the attributes it will have along with the types of data they will have.

const mongoose = require('mongoose');const accountSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: String,
password: String
});
module.exports = mongoose.model('Account', accountSchema);

12. At the top of the earlier app.js file add the following code.

const express = require('express')
const app = express()
const mongoose = require('mongoose')
const bodyparser = require('body-parser')
const accountRoutes = require('./api/routes/accounts')app.use(bodyparser.json())
app.use('/', accountRoutes)
app.use(express.json());
  • Here we are importing and using express to set up a server with router, importing mongoose, and importing the account models we just set up.
  • Move the earlier mongoose.connect line in after the third app.use line
  • We are also importing the routes from the accounts.js file inside routes file which we didn’t set up yet. These routes determines how we can interact with the database and how we would do it.

13. Now create an accounts.js file inside of the routes folder (notice this has a plural, unlike the model folder which is singular.) and add the following code.

const express = require('express')
const router = express.Router()
const mongoose = require('mongoose')

accountRoutes = require('../models/account')
module.exports = router

14. Set up the routes inside the accounts.js file

a) a route to get back all accounts

  • This route retrieves all accounts, console logs the result, and returns the result if the request successfully completes, while console logging and returning a 500 error if it doesn’t.
router.get("/api/accounts", (req, res) => {
Account.find()
.exec()
.then(docs => {
console.log(docs)
res.status(200).json(docs)
})
.catch(err => {
console.log(err)
res.status(500).json({
error: err
})
})
})

b) a route to get one account

  • Similar to the get all accounts but since an id is passed inside the route, an account with a matching id is found, console logged, and returned. If the request fails there will be a 500 error, but also if no account with a matching id is found a 404 error will be returned.
router.get("/api/accounts/:id", (req, res) => {
const id = req.params.id
Account.findById(id)
.exec()
.then(doc => {
console.log(doc)
if (doc) {
res.status(200).json(doc)
} else {
res.status(404).json({message: 'No valid entry found for provided ID'})
}
})
.catch(err => {
console.log(err)
res.status(500).son({error: err})
})
})

c) a route to post (create a new account)

  • Here the route takes an object passed in inside the body and uses the properties of that object to create a new account. The newly created account is console logged and returned. A 500 error is returned if it fails.
router.post("/api/accounts", (req, res) => {
const account = new Account({
_id: new mongoose.Types.ObjectId(),
name: req.body.name,
password: req.body.password
})
account.save()
.then(result => {
console.log(result)
res.status(201).json({
message: "Handling POST requests to /accounts",
createdAccount: account
})
})
.catch(err => {
console.log(err)
res.status(500).json({
error: err
})
});
})
  • You would pass in something like:
{
name: newName,
password: newPassword
}

d) a route to patch (change the attributes of an existing account)

  • This step finds an account with a matching id, then changes the attributes of the account with that id to the attributes of a new object passed in through the body. The newly updated object is console logged and returned. A 500 error is returned if it failed.
router.patch("/api/accounts/:id", (req, res) => {
const id = req.params.id
Account.update({_id: id}, { $set: {name: req.body.newName, password: req.body.newPassword} })
.exec()
.then(result => {
console.log(result)
res.status(200).json(result)
})
.catch(err => {
console.log(err)
res.status(500).json({
error: err
})
})
})
  • You would pass in something like:
{
"newName": "Yugi264",
"newPassword": "abcdefg"
}
  • Your object’s name and password will be changed to the newName value and newPassword value of the passed in object.

e) And finally, a route to delete

  • This also passes in an id to find an account with, and that account is then deleted. A 500 error is returned if it failed.
router.delete("/api/accounts/:id", (req, res) => {
const id = req.params.id
Account.remove({_id: id})
.exec()
.then(result => {
res.status(200).json(result)
})
.catch(err => {
console.log(err)
res.status(500).json({
error: err
})
})
})

If we try using postman to perform any crud operation, you will see a change in the contents of your api, as well as in your mongoDB page. Congratulations! We now have a Node.js API that connects to a MongoDB database that you can create, read, update, and delete objects from/to!

--

--