In our previous blog, we explored the fundamentals of creating a REST API with in-memory CRUD operations using Node.js and Express. Now, we’re taking a significant step forward by integrating our product data with a database. This transition is pivotal for achieving data persistence and scalability in real-world applications. In this blog, we will dive into the process of connecting to a chosen database, MongoDB, setting up the database schema and models, and seamlessly migrating our existing in-memory data. Additionally, we’ll walk through performing CRUD operations with the connected database, addressing asynchronous challenges in Node.js, and sharing best practices for error handling and testing. This shift marks a crucial evolution in our application architecture, ensuring long-term data integrity and robustness.
Link to the blog: https://iot4beginners.com/how-to-create-rest-api-using-node-js-and-express/
We will see the following topics in this blog.
- MongoDB
- Installation of MongoDB
- Mongoose – Model and Schema
- Development: Set up the Project
- CRUD Operation
- POST
- PUT
- DELETE
- GET
MongoDB
MongoDB is a popular NoSQL database that stores data in flexible, JSON-like BSON documents. Unlike traditional relational databases, MongoDB’s document-oriented approach allows for dynamic schemas, making it well-suited for handling unstructured or semi-structured data. Key features include horizontal scalability, automatic sharing, and support for a rich query language.
We will see the important 5 differences between SQL and MongoDB
Feature | SQL Database | MongoDB |
---|---|---|
Data Structure | Relational tables with predefined schemas. | Document-oriented, allowing flexible and dynamic schemas. |
Query Language | SQL for structured queries, supports complex joins. | MongoDB Query Language (MQL) for rich and flexible queries. |
Scalability | Vertical scaling (adding more power to existing hardware). | Horizontal scaling (adding more servers to a database cluster). |
Schema Flexibility | Rigid, requires predefined schemas for each table. | Dynamic schema allows changes without affecting existing data. |
Use Cases | Well-suited for applications with complex relationships and transactions. | Ideal for projects with evolving or unstructured data, such as content management systems and real-time applications. |
Installation
Installing MongoDB is straightforward, and the steps may vary slightly depending on your operating system. Here’s a concise guide for a generic installation:
Step 1: Download MongoDB. Visit the official MongoDB website and download the appropriate version for your operating system. Make an account for yourself and download MongoDB Compass also.
Step 2: Build a Database. Once signed in, navigate to the section or option that allows you to create a new database. This might be labeled as “Build a Database” or something similar. Click on this option to initiate the database creation process.
Select your options for deploying your database.
Assign a username and password to your database.
Assign your IP address as 0.0.0.0/0 and add an optional comment. If you have accidently selected My IP address, you can always chane under the Network Access.
I’ve established a cluster named “iotedu-api,” but feel free to create one with a name of your choosing.
Step 3: Connect Database. When you click the cutton Connect, you will have the follwing page opened.
Choose your driver: Node.js and the version. Importantly, copy the contents 3. Add your connection string into your application code.
In my case it is, mongodb+srv://monisha:password1104@iotedu-api.pjawowz.mongodb.net/node-crud?retryWrites=true&w=majority&appName=iotedu-api. This content will be the URL to connect your database from Node.js
Development: Set up the Project
Until, we have created a database cluster an copied the contents of the URL. Now, open your VS Code (your previous project). If you have not set up your project, you can still start from the scratch.
mkdir nodeProject cd nodeProject npm init -y npm install express mongoose --save
Execute the outlined steps in the terminal, and note that there’s an additional aspect: we’re installing Mongoose in conjunction with Express.
To connect a Node.js application to MongoDB, we have to use a library called Mongoose. Firstly, we will learn some concepts of Mongoose.
- Mongoose:
- Mongoose is an Object Data Modeling (ODM) library for MongoDB and Node.js. It provides a structured way to interact with MongoDB databases by defining models and schemas.
- Schema:
- In Mongoose, a schema is a blueprint that defines the structure of the documents within a collection in MongoDB. It specifies the fields, their types, and any validation rules.
- Model:
- A model, in the context of Mongoose, is a constructor function based on a schema. It allows you to interact with the MongoDB collection associated with that schema. Models provide an interface for creating, reading, updating, and deleting documents in the database.
Now, let’s connect these elements:
- You define a Product Schema using Mongoose. This schema outlines the structure of the documents that will be stored in the MongoDB collection for products. It could include fields like “name,” “price,” “category,” etc.
- Using the defined schema, you create a Product Model. This model is a Mongoose construct that acts as an interface for performing database operations related to products. It is associated with the MongoDB collection that adheres to the defined schema.
- In your Node.js application, you use the Product Model to perform CRUD operations on the MongoDB database. For example, you can create a new product, retrieve a list of products, update product details, or delete a product—all using methods provided by the Product Model.
- The connection between the Product Model, Schema, Node.js, and MongoDB is facilitated by Mongoose. Mongoose helps you establish a connection to the MongoDB database, defines how data should be structured (schema), and provides a convenient way to interact with that data through models.
in your project, open index.js and copy the following code.
const express = require("express"); const mongoose = require("mongoose"); const Product = require("./schema/productModel.js"); const app = express(); app.use(express.json()); app.get("/", async (req, res) => { console.log("Hello World"); res.send("Hello World"); }); //read app.get("/api/products", async (req, res) => { try { const product = await Product.find({}); res.status(200).json(product); } catch (error) { res.status(500).json({ message: error.message }); } }); //post app.post("/api/products", async (req, res) => { try { const product = await Product.create(req.body); res.status(200).json(product); } catch (error) { res.status(500).json({ message: error.message }); } }); //delete app.delete("/api/products/:id", async (req, res) => { try { const { id } = req.params; const product = await Product.findByIdAndDelete(id, req.body); res.status(200).json(product); } catch (error) { res.status(500).json({ message: error.message }); } }); const url = "mongodb+srv://monisha:password1104@iotedu-api.pjawowz.mongodb.net/node-crud?retryWrites=true&w=majority&appName=iotedu-api"; mongoose.set("strictQuery", false); mongoose.connect(url, { useNewUrlParser: true }); const connect = mongoose.connection; connect.on("open", () => { console.log("connected..."); }); app.listen(3000, () => { console.log("Server started"); });
Paste the copied URL into your code, ensuring that the URL includes the database name. In my case it is, node-crud.
Create a new folder called “schema”, and create a file called “productModel.js“
const mongoose = require("mongoose"); const productSchema = mongoose.Schema( { name: { type: String, required: true, default: "", }, price: { type: Number, required: true, }, quantity: { type: Number, required: true, default: 0, }, }, { timestamps: true } ); const Product = mongoose.model("Product", productSchema); module.exports = Product;
Your file structure should look like this:
nodeProject
│
├── index.js
└── schema
└── productModel.js
When you run the index.js using nodemon or node, you will see the server has started and connected successfully to the port.
CRUD Operations
POST
First, we will post some product data in our database. Open postman, and give the following command and select POST.
localhost://3000/api/products/
{ "name": "candles", "price": 25, "quantity": 4 }
You have successfully posted a json product data in the database. Now open the MongoDB application, click on Collections and you can find your database.
Following this step, you can effectively post an array of data into your database. Paste the provided array into Postman to proceed.
[ { "name": "candles", "price": 25, "quantity": 4 }, { "name": "resin", "price": 56, "quantity": 9 }, { "name": "paraffin wax", "price": 85, "quantity": 74 }, { "name": "soap", "price": 10, "quantity": 45 }, { "name": "coconut oil", "price": 25, "quantity": 6 } ]
After posting the JSON array into your database, you may observe a repetition in the product data, specifically with the key “candles” appearing twice. Now, it’s time to perform a delete operation to address this redundancy.
DELETE
Now, proceed with the deletion of the object by its unique identifier. Copy the ID and paste it into the following command:
We will use a function called findByIdAndDelete to delete the object in the array.
localhost:3000/api/products/65eb1ce5b37f4d0c9a2ad4b1
PUT
To update existing data in the database, the findByIdAndUpdate
function can be employed. This function allows you to modify data based on the product’s unique identifier (ID). Here’s a general explanation:
Update Data Using findByIdAndUpdate: To update a product’s information, use the findByIdAndUpdate
function. Send a PUT or PATCH request to the following endpoint, specifying the product’s ID in the URL:
PUT or PATCH localhost:3000/api/products/your_product_id
Replace your_product_id
with the actual ID of the product you want to update.
Include the updated data in the request body. Depending on your application, you might send a JSON object with the modified fields.
//put app.put("/api/products/:id", async (req, res) => { try { const { id } = req.params; const product = await Product.findByIdAndUpdate(id, req.body); res.status(200).json(product); } catch (error) { res.status(500).json({ message: error.message }); } });
GET
You can retrieve a single object by using the findById
function. Additionally, you can fetch all products with a separate endpoint. Here’s a brief explanation:
- Retrieve a Single Object by ID (Using
findById
):- Utilize the
findById
function to fetch a single product based on its unique identifier. For example:plaintextCopy codelocalhost:3000/api/products/your_product_id
Replaceyour_product_id
with the actual ID of the product you want to retrieve.
- Utilize the
- Get All Products:
- Use a dedicated endpoint to retrieve all products. For instance:plaintextCopy code
localhost:3000/api/products
This endpoint should return a list of all products in your database.
- Use a dedicated endpoint to retrieve all products. For instance:plaintextCopy code
Ensure that your Express routes and Mongoose queries are set up appropriately to handle these requests.
In conclusion, this blog has provided a comprehensive exploration of CRUD operations with MongoDB and Express, illustrating the fundamental steps to create, read, update, and delete data in a Node.js application. We initiated the journey by setting up an Express server, establishing a connection to MongoDB using Mongoose, and defining a schema for our product data. The transition from in-memory storage to a MongoDB database highlighted the advantages of persistence and scalability in real-world applications.