Skip to main content

Basic Example

Let's Start

We've learned how to use mongoose with express, how to create a schema, create a model, and how to do CRUD operations on the database. Now, we'll create a simple project and will use MongoDB with it.

First of all, I am creating and naming it express-with-mongodb.

mkdir express-with-mongodb

I am going to use Modular Routing in this doc, but for books, will follow the same structure as we did in the Modular Routing doc, plus I'll add some extra code like models, and importing the model to the routes to interact with the database.

Go to express-with-mongodb directory (folder)

Change directory to express-with-mongodb
cd express-with-mongodb

Now run this command to create a project

npm init -y

It'll create a package.json file like this 👇

package.json
{
"name": "express-with-mongodb",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "commonjs",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "@mrizwanashiq",
"license": "ISC"
}

Now, install express, mongoose, nodemon

npm install express mongoose nodemon

I am making some changes to the package.json file, and the final version of it is:

package.json
{
"name": "express-with-mongodb",
"version": "1.0.0",
"description": "test project",
"main": "index.js",
"type": "module",
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js"
},
"author": "@mrizwanashiq",
"license": "ISC",
"dependencies": {
"express": "^4.17.3",
"mongoose": "^6.3.3",
"nodemon": "^2.0.15"
}
}

Folder structure

The folder structure will be like this:

Folder Structure
📂 express-with-mongodb
├── 📂 models
│ └── 📄 book.js
├── 📂 routes
│ └── 📄 book.js
├── 📄 index.js
└── 📄 package.json

index.js

Here, we'll create a simple express app and connect it to the database. We'll use mongoose to connect to the database. For now, I am using a local database, but you can use any database you want. There's no route, we'll add it later.

index.js
import express from "express";
import mongoose from "mongoose";

const app = express();
app.use(express.json());

// Below 👇 code is connecting our Express App to MongoDB
const connection = mongoose.connection;
/**
* 1. First, we created a connection variable and assigned it to the mongoose.connection
*/

connection.once("connected", () => console.log("Database Connected ~"));
/**
* 2. connection.once() will run once the connection is established
* and will print out the message "Database Connected ~" in the console
* to let us know that the connection is established
*/

connection.on("error", (error) => console.log("Database Error: ", error));

/**
* 3. connection.on() will run every time there is an error
* and will print out the message "Database Error: " and the error
* for example, if the connection string is wrong, it will print out the error
*/
mongoose.connect("mongodb://127.0.0.1:27017/my_first_data_base", {
useNewUrlParser: true,
useUnifiedTopology: true,
});

/**
* 4. mongoose.connect() will connect to the database
* and will use the connection string "mongodb://127.0.0.1:27017/my_first_data_base"
* We are using 127.0.0.1 (localhost) because we are running the database locally
* 27017 is the port number
* my_first_data_base is the name of the database
*/

app.listen(9999);

models/book.js:

First, create a folder named models and inside it create a file named book.js. Here, we'll create a schema and a model for the book collection. In the previous section, we learned in detail about schema and models. So, no need to explain it again.

Define the schema with the following properties:

  • name: String (required, and must be unique)
  • author: String (required)
  • price: Number (required, and must be greater than 0)
  • stock: Number (optional)

Then we'll create a model using the schema. The model's name will be Book, and Mongoose will automatically lowercase and pluralize it, so the collection's name will be books.

models/book.js
import mongoose from "mongoose";

// Here 👇 it is, the schema
const schema = mongoose.Schema({
name: { type: String, required: true, unique: true },
author: { type: String, required: true },
price: { type: Number, required: true, min: 0 },
stock: { type: Number },
});

// The model's name is "Book" 👇 (collection becomes "books"). That's how we create the model using schema
const bookModel = mongoose.model("Book", schema);

// Exporting the model so that we can use it in other files
export default bookModel;

routes/book.js:

Here, we'll create the routes for the book collection. We'll create the following routes:

  • GET /book - to get all the books
  • GET /book/:id - to get a single book
  • POST /book - to create a new book
  • PATCH /book/:id - to update a book
  • DELETE /book/:id - to delete a book
  • DELETE /book - to delete all the books

Let's start:

routes/book.js
import express from "express";
const router = express.Router();
import bookModel from "../models/book.js";

router.get("/", async (req, res) => {
/**
* I am using a try-catch block to handle the error
* if there is any error in the code
* it will be handled by the catch block
* and the error will be returned via the response
* and the user will be notified
*
* And I will use the try-catch block everywhere in the code
* where there is a possibility of error because it is a good practice
* I don't want to crash the whole application if there is an error
* I want to handle the error and return the user a response
*/

try {
const books = await bookModel.find();
res.json(books);
} catch ({ message }) {
res.json({ message });
}
});

router.get("/:id", async (req, res) => {
try {
const book = await bookModel.findById(req.params.id);
res.json(book);
} catch ({ message }) {
res.json({ message });
}
});

router.post("/", async (req, res) => {
try {
const result = await bookModel.create(req.body);
res.status(200).json(result);
} catch ({ message }) {
res.json({ message });
}
});

router.patch("/:id", async (req, res) => {
try {
const result = await bookModel.findByIdAndUpdate(req.params.id, req.body);
res.status(200).json(result);
} catch ({ message }) {
res.json({ message });
}
});

router.delete("/:id", async (req, res) => {
try {
const result = await bookModel.findByIdAndDelete(req.params.id);
res.status(200).json(result);
} catch ({ message }) {
res.json({ message });
}
});

router.delete("/", async (req, res) => {
try {
const result = await bookModel.deleteMany();
res.status(200).json(result);
} catch ({ message }) {
res.json({ message });
}
});

export default router;

That's it. Now, let's import the bookRouter in the index.js file and use it.

Modifying index.js:

Here, will import the bookRouter and use it.

index.js
import express from "express";
import mongoose from "mongoose";
import bookRouter from "./routes/book.js";

const app = express();
app.use(express.json());

// Below code is connecting our Express App to MongoDB
const connection = mongoose.connection;
/**
* 1. First, we created a connection variable and assigned it to the mongoose.connection
*/

connection.once("connected", () => console.log("Database Connected ~"));
/**
* 2. connection.once() will run once the connection is established
* and will print out the message "Database Connected"
*/

connection.on("error", (error) => console.log("Database Error: ", error));

/**
* 3. connection.on() will run every time there is an error
* and will print out the message "Database Error: " and the error
*/
mongoose.connect("mongodb://127.0.0.1:27017/my_first_data_base", {
useNewUrlParser: true,
useUnifiedTopology: true,
});

/**
* 4. mongoose.connect() will connect to the database
* and will use the connection string "mongodb://127.0.0.1:27017/my_first_data_base"
* We are using 127.0.0.1 (localhost) because we are running the database locally
* 27017 is the port number
* my_first_data_base is the name of the database
*/

app.use("/book", bookRouter);

app.listen(9999);

Testing the API:

Now, test the APIs using any API testing tool like Postman, and see if it is working or not.

Code

You can download the related code from here

Conclusion

In this article, we learned how to connect the Express App to MongoDB and how to create a CRUD API for a book collection.