How to Use MongoDB and Node.js to Build a REST API

Node.js

In this tutorial I will show you how to interact with a MongoDB database with Node.js.

Mongoose

Let’s use the mongoosejs package. If you already have a Node.js project you are working on, install it using:

$ npm install mongoose

If you are starting from scratch, you can take a look at my introduction to Node.js or start by creating a new folder, and with your terminal inside the folder, run the npm init -y command to start a new Node.js project, and then run the npm install mongoose command.

Connecting to MongoDB

Create a new server.js file. You will first need the mongoose package in your project. So, let’s import it.

const mongoose = require('mongoose');

Create a URL for the MongoDB server. If you’re using MongoDB locally, the URL is something like mongodb://localhost:27017, 27017 is the default port for MongoDB. And create another variable with the name of your database.

The package comes with a method called connect() that will help us connect to MongoDB. We will use this method to create a database instance.

const mongoose = require('mongoose');
const server = 'mongodb://localhost:27017'
const database = 'myDatabase';
mongoose.connect(`${server}/${database}`,
   { useNewUrlParser: true, useUnifiedTopology: true }
);

The Mongoose package has some depreciations in the project, due to changes in MongoDB, so we need to use the {useNewUrlParser: true, useUnifiedTopology: true } flags, if you want to see more details, just click here.

We can then test whether the connection was successful or not.

const mongoose = require('mongoose');
const server = 'mongodb://localhost:27017'
const database = 'myDatabase';
mongoose.connect(`${server}/${database}`,
   { useNewUrlParser: true, useUnifiedTopology: true }
).then(() => {
   console.log("Successfully connect to MongoDB.");
})
   .catch(err => {
      console.error("Connection error", err);
      process.exit();
   });

In your terminal, run the command node server.js. You should see this message in your terminal:

Successfully connect to MongoDB.

Creating a collection

Everything in mongoose starts with a Schema. Each schema maps to a collection. Collections are one of the basic structures of MongoDB. MongoDB defines the form of the documents within this collection.

  const Schema = mongoose.Schema;
  const UserSchema = new Schema({
    name:  String
  });

Creating a document

An instance of a model is called a document. We will then use our model() method to create our document.

const User = mongoose.model('User', UserSchema);

The first argument is the singular name of the collection for which your model is targeted. The second argument is the Schema object from our collection that we defined before, UserSchema.

Mongoose will automatically search for the lower case plural version of your model name.

Inserting Data in a Document

With our User document created, saving the data to the database is simple. We will create a new instance of the document and pass the data we want to insert, in our example, our model accepts only the attribute name. We can then use the save() method directly in our model to persist the data.

const user = new User({ name: 'John' });
user.save()
   .then(() => console.log('User Created'))
   .catch(() => console.log('User model Error'))

You can test using the command, node server.js in your terminal. You should see this message.

Successfully connect to MongoDB.
User Created

You can add several items using the create() method, passing an Array as the first parameter. This method performs the save() method for each Array item.

const userArray = [{ name: 'Alice' }, { name: 'Paul' }]
User.create(userArray)
   .then(() => console.log('User Created'))
   .catch(() => console.log('User model Error'))

Find all the documents in a collection

Mongoose has a very simple method to solve this. With the find() method being called in your model, you can recover all the documents in your collection.

User.find()
   .then(users => { console.log(users) })
   .catch(error => { console.log("User Find Error", error) })

Your result in the terminal after running the node server.js command should be something like this:

Successfully connect to MongoDB.
[ { _id: '5f05a2b58415d87a550de613', name: 'Alice', __v: 0 },
  { _id: '5f05a2b58415d87a550de614', name: 'Paul', __v: 0 },
  { _id: '5f05a4c99f222e7e9c96d825', name: 'John', __v: 0 } ]

Find a specific document

You can filter the documents by passing the list of parameters within the find() method. This process is similar to SQL WHERE.

As we have only one attribute in our documents, we will filter by each user name.

User.find({ name: 'John' })
   .then(user => { console.log(user); })
   .catch(error => { console.log("User Find Error", error) })

And that must be your result:

Successfully connect to MongoDB.
[ { _id: '5f05a4c99f222e7e9c96d825', name: 'John', __v: 0 } ]

If you need to find more than one document you can use the $in operator.

User.find({ name: { $in: ['John', 'Paul'] } })
   .then(users => { console.log(users); })
   .catch(error => { console.log("User Find Error", error) })
Successfully connect to MongoDB.
[ { _id: '5f05a2b58415d87a550de614', name: 'Paul', __v: 0 },
  { _id: '5f05a4c99f222e7e9c96d825', name: 'John', __v: 0 } ]

Update an existing document

Below is an example of how to use save() to update the user name.

async function update(name, newName) {
   try {
      const user = await User.findOne({ name: name });
      if (user) {
         user.name = newName;
         await user.save();
         console.log('User Updated');
      }
      console.log('User not Found!');
      return;
   } catch (error) {
      console.log('Update Error', error);
      return;
   }
}
update('Paul', 'Peter');

This simple example has some nuances. First, the save() method is a document method, which means you must have a document to use it. You must use the create() method or use find() to get a document.

I’m using the findOne() method because it returns only one document, the find() method returns an Array, even if it finds only one match.

Secondly, the documents have change tracking. When you call doc.save(), Mongoose knows that you have changed the name property and turned your save() call into updateOne({ $set: { name } }).

If you prefer to use Promises, you can eliminate the use of the function by doing so:

User.findOne({ name: "Paul" })
   .then(user => {
      if (user) {
         user.name = 'Peter';
         user.save();
         console.log('User Updated');
      }
      console.log('User not Found!');
   })
   .catch(error => {
      console.log('Update Error', error);
   })

Deleting a document

The method we’ll use is deleteOne(), this method calls the Collection#deleteOne() function from MongoDB Driver. The returned promise resolves for an object that contains 3 properties:

  • ok: 1 if no errors occur
  • deletedCount: the number of documents deleted
  • n: the number of documents deleted. Same as deletedCount.
User.deleteOne({ name: 'John' })
   .then(response => { console.log(response) })
   .catch(error => { console.log('Delete Error', error); })

The result of our example in the terminal:

{ n: 1, ok: 1, deletedCount: 1 }

Ending the connection

Once the operations are finished, we can call the method close():

mongoose.connection.close();

If you like this article, be sure to subscribe to the newsletter and stay informed whenever you have new content!

And if you still have any questions, or if you have any suggestions, you can leave your comment right here below! See you next time.

Leave a Reply

Your email address will not be published. Required fields are marked *

0 Comments