Home Blog Page 77

MongoDB Integration with Express (Basic REST API)

0
mongodb course
mongodb course

Table of Contents

  1. Introduction to Express and MongoDB Integration
  2. Setting Up MongoDB with Express
  3. Installing Dependencies
  4. Setting Up the MongoDB Database Connection
  5. Defining the Schema and Model
  6. Creating Basic CRUD Operations
    • Create Operation (POST)
    • Read Operation (GET)
    • Update Operation (PUT)
    • Delete Operation (DELETE)
  7. Testing the REST API
  8. Error Handling and Validation
  9. Conclusion

1. Introduction to Express and MongoDB Integration

Express is a lightweight and flexible web application framework for Node.js. MongoDB, on the other hand, is a NoSQL database that stores data in a flexible, JSON-like format called BSON. Integrating MongoDB with Express allows you to build dynamic and scalable web applications that can handle large volumes of data with ease.

In this article, we will learn how to integrate MongoDB with an Express application to create a basic REST API that performs CRUD operations (Create, Read, Update, Delete).


2. Setting Up MongoDB with Express

Before we begin coding, ensure that you have the following prerequisites in place:

  • Node.js and npm installed on your machine.
  • MongoDB running locally or using a cloud service like MongoDB Atlas.
  • A code editor like VS Code.

3. Installing Dependencies

To set up the integration between Express and MongoDB, we need a few dependencies:

  • Express: The web application framework.
  • Mongoose: An Object Data Modeling (ODM) library for MongoDB and Node.js, which simplifies interacting with MongoDB by providing a schema-based solution.
  • Body-Parser: Middleware to parse incoming request bodies.

You can install these dependencies via npm by running the following command:

npm install express mongoose body-parser

4. Setting Up the MongoDB Database Connection

Now that we have our dependencies installed, the next step is to connect to MongoDB using Mongoose. Create a file named server.js or app.js (or any name you prefer) and set up your Express server.

Example Code for Connecting to MongoDB

const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');

const app = express();

// Middleware to parse JSON data
app.use(bodyParser.json());

// MongoDB connection string (Local or MongoDB Atlas URI)
const dbURI = 'mongodb://localhost:27017/myDatabase'; // Use your MongoDB URI

mongoose.connect(dbURI, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => {
console.log('Connected to MongoDB');
})
.catch((err) => {
console.log('Error connecting to MongoDB:', err);
});

In this code:

  • We use mongoose.connect() to establish a connection to the database.
  • useNewUrlParser: true and useUnifiedTopology: true are configuration options to avoid deprecation warnings.
  • body-parser.json() is middleware that ensures we can parse JSON payloads sent to our API.

5. Defining the Schema and Model

With the database connection established, we now define the data structure. In MongoDB, data is stored as documents within collections. Mongoose provides an elegant way to model data using Schemas and Models.

Let’s say we are building a simple Todo API. We will define a schema for the todo tasks.

Example: Defining a Todo Schema

const mongoose = require('mongoose');

const todoSchema = new mongoose.Schema({
title: { type: String, required: true },
description: { type: String, required: true },
completed: { type: Boolean, default: false },
createdAt: { type: Date, default: Date.now },
});

// Create a model based on the schema
const Todo = mongoose.model('Todo', todoSchema);

module.exports = Todo;

In this code, we define a Todo schema with the following fields:

  • title: A required string field for the title of the task.
  • description: A required string field for the task description.
  • completed: A boolean field indicating whether the task is completed, with a default value of false.
  • createdAt: A date field with a default value of the current date and time.

6. Creating Basic CRUD Operations

Now that we have our model defined, let’s set up the CRUD operations (Create, Read, Update, and Delete) for our Todo API.

Create Operation (POST)

To create a new todo item, we use the POST method. Here’s the route to handle the creation of a new todo.

app.post('/todos', async (req, res) => {
const { title, description } = req.body;

try {
const todo = new Todo({
title,
description,
});

const savedTodo = await todo.save();
res.status(201).json(savedTodo);
} catch (error) {
res.status(400).json({ message: 'Error creating Todo' });
}
});

Read Operation (GET)

To fetch all todo items, we use the GET method.

app.get('/todos', async (req, res) => {
try {
const todos = await Todo.find();
res.status(200).json(todos);
} catch (error) {
res.status(400).json({ message: 'Error fetching Todos' });
}
});

To fetch a specific todo by ID, we can modify the route:

app.get('/todos/:id', async (req, res) => {
const { id } = req.params;

try {
const todo = await Todo.findById(id);
if (!todo) {
return res.status(404).json({ message: 'Todo not found' });
}
res.status(200).json(todo);
} catch (error) {
res.status(400).json({ message: 'Error fetching Todo' });
}
});

Update Operation (PUT)

To update a todo item, we use the PUT method. This allows the user to update the fields of an existing todo item.

app.put('/todos/:id', async (req, res) => {
const { id } = req.params;
const { title, description, completed } = req.body;

try {
const updatedTodo = await Todo.findByIdAndUpdate(
id,
{ title, description, completed },
{ new: true } // Returns the updated document
);

if (!updatedTodo) {
return res.status(404).json({ message: 'Todo not found' });
}
res.status(200).json(updatedTodo);
} catch (error) {
res.status(400).json({ message: 'Error updating Todo' });
}
});

Delete Operation (DELETE)

To delete a todo item, we use the DELETE method.

app.delete('/todos/:id', async (req, res) => {
const { id } = req.params;

try {
const deletedTodo = await Todo.findByIdAndDelete(id);
if (!deletedTodo) {
return res.status(404).json({ message: 'Todo not found' });
}
res.status(200).json({ message: 'Todo deleted' });
} catch (error) {
res.status(400).json({ message: 'Error deleting Todo' });
}
});

7. Testing the REST API

To test our API, we can use Postman or cURL to send requests to the server. Make sure your MongoDB server is running and the Express server is listening on a port (usually 3000).


8. Error Handling and Validation

When building REST APIs, proper error handling and input validation are critical. You can enhance your API by validating incoming data before performing any operations.

For example, you can ensure that required fields are present before saving a new todo item:

app.post('/todos', async (req, res) => {
const { title, description } = req.body;

if (!title || !description) {
return res.status(400).json({ message: 'Title and Description are required' });
}

// Proceed with the rest of the logic
});

9. Conclusion

Integrating MongoDB with Express allows developers to build efficient and scalable REST APIs. Using Mongoose as an ORM simplifies working with MongoDB by providing schema validation, powerful querying, and model-based interaction with MongoDB documents.

Schema Definition and Validation with Mongoose

0
mongodb course
mongodb course

Table of Contents

  1. Introduction to Mongoose Schema
  2. Defining a Mongoose Schema
  3. Mongoose Schema Types
  4. Setting Default Values
  5. Mongoose Validation
    • Built-in Validation
    • Custom Validation
    • Async Validation
  6. Validating Arrays and Nested Objects
  7. Required Fields and Field Constraints
  8. Schema Methods and Virtuals
  9. Schema Indexing
  10. Best Practices for Schema Definition and Validation
  11. Conclusion

1. Introduction to Mongoose Schema

In Mongoose, a Schema is the structure that defines how data should be stored in MongoDB. It acts as a blueprint for creating MongoDB documents that comply with specific data constraints and business logic. Mongoose schemas provide a strongly defined structure that makes data manipulation more predictable and manageable.

Schemas are used to create Mongoose Models, which provide a way to interact with MongoDB collections, perform CRUD operations, and define validation rules. By using schemas, developers can enforce consistency, validate data, and define relationships between different documents.


2. Defining a Mongoose Schema

Defining a schema in Mongoose involves creating a new instance of mongoose.Schema and specifying the fields and their properties. Here is an example of a basic schema for a User:

Example: Defining a Basic User Schema

const mongoose = require('mongoose');

// Define the schema
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true, // This field must be provided
minlength: 3, // Minimum length of the name
maxlength: 100, // Maximum length of the name
},
email: {
type: String,
required: true,
unique: true, // Ensures the email is unique
match: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/, // Email format validation
},
age: {
type: Number,
min: 18, // Minimum age
max: 120, // Maximum age
default: 18, // Default value if not provided
},
address: {
type: String,
default: 'Unknown',
}
});

// Create a model based on the schema
const User = mongoose.model('User', userSchema);

In this example, we have a User schema with fields for name, email, age, and address. We have added validation rules to ensure the name is at least 3 characters long, the email is unique, and the age is within a specific range.


3. Mongoose Schema Types

Mongoose supports a wide variety of data types that can be used in your schema. These include basic types like String, Number, and Date, as well as more advanced types such as arrays, buffers, and mixed types.

Common Schema Types:

  • String: Text data.
  • Number: Numeric data.
  • Date: Date values.
  • Boolean: true or false.
  • Buffer: Binary data.
  • Mixed: Can hold any type of data.
  • Array: An array of values.

Example:

const productSchema = new mongoose.Schema({
name: String,
price: Number,
tags: [String], // Array of Strings
images: [Buffer], // Array of binary data (e.g., image files)
});

4. Setting Default Values

Default values are useful when you want certain fields to automatically get a value if none is provided during document creation. In Mongoose, you can define default values for schema fields.

Example:

const userSchema = new mongoose.Schema({
name: { type: String, required: true },
age: { type: Number, default: 18 },
role: { type: String, default: 'user' },
});

In this case, if the age or role is not provided, Mongoose will use the default values of 18 and 'user', respectively.


5. Mongoose Validation

Mongoose provides built-in validators to ensure the integrity of your data before it gets saved to the database. These validators can be applied to individual fields in your schema.

Built-in Validation

Mongoose supports various built-in validation types, including:

  • required: Ensures the field is not empty.
  • min / max: Validates numbers or strings within a specified range.
  • enum: Restricts the field to specific values.
  • match: Validates data using regular expressions (useful for validating emails, phone numbers, etc.).

Custom Validation

You can also define custom validation logic using functions. Custom validators are ideal for cases when you need more complex validation beyond built-in methods.

const userSchema = new mongoose.Schema({
name: { type: String, required: true },
email: {
type: String,
required: true,
validate: {
validator: function(v) {
return /^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$/.test(v);
},
message: props => `${props.value} is not a valid email address!`
}
}
});

Async Validation

In some cases, validation may need to involve asynchronous logic (such as checking whether a username is already taken). You can use asynchronous validators in Mongoose:

const userSchema = new mongoose.Schema({
username: {
type: String,
required: true,
unique: true,
validate: {
async validator(value) {
const user = await User.findOne({ username: value });
return !user; // Return true if username is unique
},
message: 'Username already exists!',
}
}
});

6. Validating Arrays and Nested Objects

Mongoose allows you to apply validation to nested objects and arrays. This is particularly useful when you have complex data structures.

Example: Array Validation

const postSchema = new mongoose.Schema({
title: { type: String, required: true },
tags: {
type: [String],
validate: {
validator: function(v) {
return v.length > 0; // Ensures the tags array is not empty
},
message: 'A post must have at least one tag!'
}
}
});

Example: Nested Object Validation

const userSchema = new mongoose.Schema({
name: String,
contact: {
phone: { type: String, required: true },
email: { type: String, required: true },
}
});

7. Required Fields and Field Constraints

Mongoose allows you to apply constraints to your fields to ensure that required fields are provided and that the values follow specific rules.

Example: Required Fields and Constraints

const eventSchema = new mongoose.Schema({
name: { type: String, required: true }, // Required field
startDate: { type: Date, required: true, min: '2021-01-01' }, // Date after January 1, 2021
description: { type: String, maxlength: 500 }, // Max 500 characters
});

8. Schema Methods and Virtuals

Mongoose provides the ability to define instance methods (for individual documents) and virtuals (computed fields that don’t exist in the database).

Example: Schema Method

userSchema.methods.greet = function() {
return `Hello, ${this.name}!`;
};

Example: Virtual Field

userSchema.virtual('fullName').get(function() {
return `${this.firstName} ${this.lastName}`;
});

9. Schema Indexing

Indexes improve the performance of database queries. Mongoose allows you to define indexes on specific fields for faster retrieval of documents.

Example: Creating Indexes

userSchema.index({ email: 1 }); // Create an index on the 'email' field

10. Best Practices for Schema Definition and Validation

  1. Use Built-in Validation: Always use Mongoose’s built-in validation methods wherever possible to ensure data integrity.
  2. Define Default Values: Provide default values for fields that should always have a fallback value.
  3. Custom Validation: For complex validation logic, define custom validators for greater flexibility.
  4. Use Indexing for Performance: Create indexes for fields that are frequently queried to improve performance.
  5. Handle Errors Gracefully: Ensure that validation errors are handled properly in your application to provide meaningful feedback.

11. Conclusion

Mongoose schemas provide a structured and flexible way to model data for MongoDB. They allow you to define validation rules, data types, and default values, as well as create complex data relationships. Leveraging Mongoose’s validation mechanisms ensures data integrity, while its schema methods and middleware offer powerful ways to interact with your

MongoDB with Mongoose ORM

0
mongodb course
mongodb course

Table of Contents

  1. Introduction to Mongoose
  2. What is an ORM (Object Relational Mapping)?
  3. Setting Up Mongoose
  4. Defining Mongoose Models
  5. CRUD Operations Using Mongoose
    • Create (insertOne, insertMany)
    • Read (findOne, find)
    • Update (updateOne, updateMany)
    • Delete (deleteOne, deleteMany)
  6. Mongoose Validation
  7. Mongoose Middleware
  8. Relationships in Mongoose (Population)
  9. Best Practices for Mongoose
  10. Conclusion

1. Introduction to Mongoose

Mongoose is a popular ODM (Object Data Mapping) library for MongoDB and Node.js. It provides a powerful schema-based solution to model your data, offering easy-to-use methods for querying, validating, and interacting with MongoDB documents. Mongoose simplifies working with MongoDB by providing schemas, models, and middleware to handle database operations.


2. What is an ORM (Object Relational Mapping)?

ORM stands for Object-Relational Mapping. It’s a technique for converting data between incompatible type systems in object-oriented programming languages, like JavaScript, and relational databases. In the case of Mongoose, it works as an ODM (Object Document Mapping), which is specifically designed for NoSQL databases like MongoDB.

  • MongoDB is a NoSQL database, which means it doesn’t store data in tables as traditional relational databases (RDBMS) do. Instead, it uses collections and documents to store data.
  • Mongoose acts as an intermediary layer between the MongoDB database and Node.js applications, allowing developers to interact with MongoDB through JavaScript objects, models, and schemas.

3. Setting Up Mongoose

To begin using Mongoose in your Node.js application, you first need to install it and set up a connection to MongoDB.

Installation

npm install mongoose dotenv

Setup .env File for Database Configuration

MONGO_URI=mongodb://127.0.0.1:27017/myapp

Establishing the Connection

const mongoose = require('mongoose');
require('dotenv').config();

mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true
}).then(() => {
console.log('MongoDB Connected');
}).catch((err) => {
console.error('Connection Error:', err);
});

This establishes a connection to MongoDB using the URI stored in the .env file.


4. Defining Mongoose Models

Mongoose uses schemas to define the structure of your documents. A schema is a blueprint for a MongoDB document, which allows you to define the fields, their types, default values, and validation rules.

Example: Defining a User Schema

const mongoose = require('mongoose');

// Create a user schema
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
age: {
type: Number,
default: 18
}
});

// Create a model based on the schema
const User = mongoose.model('User', userSchema);

In the example above, the User model is based on the userSchema, and it will allow you to interact with the users collection in MongoDB.


5. CRUD Operations Using Mongoose

Create Operation

insertOne

const newUser = new User({
name: 'John Doe',
email: '[email protected]',
age: 25
});

newUser.save().then((user) => {
console.log('User Created:', user);
}).catch((err) => {
console.error('Error:', err);
});

insertMany

User.insertMany([
{ name: 'Jane Smith', email: '[email protected]', age: 30 },
{ name: 'Alice Johnson', email: '[email protected]', age: 22 }
]).then((users) => {
console.log('Multiple Users Created:', users);
}).catch((err) => {
console.error('Error:', err);
});

Read Operation

findOne

User.findOne({ email: '[email protected]' })
.then((user) => {
console.log('User Found:', user);
})
.catch((err) => {
console.error('Error:', err);
});

find

User.find({ age: { $gt: 20 } })
.then((users) => {
console.log('Users Found:', users);
})
.catch((err) => {
console.error('Error:', err);
});

Update Operation

updateOne

User.updateOne({ email: '[email protected]' }, { $set: { age: 26 } })
.then(() => {
console.log('User Updated');
})
.catch((err) => {
console.error('Error:', err);
});

updateMany

User.updateMany({ age: { $lt: 30 } }, { $inc: { age: 1 } })
.then(() => {
console.log('Multiple Users Updated');
})
.catch((err) => {
console.error('Error:', err);
});

Delete Operation

deleteOne

User.deleteOne({ email: '[email protected]' })
.then(() => {
console.log('User Deleted');
})
.catch((err) => {
console.error('Error:', err);
});

deleteMany

User.deleteMany({ age: { $lt: 25 } })
.then(() => {
console.log('Multiple Users Deleted');
})
.catch((err) => {
console.error('Error:', err);
});

6. Mongoose Validation

Mongoose provides powerful built-in validation methods, which can be applied to individual fields within your schema.

const userSchema = new mongoose.Schema({
name: { type: String, required: true },
email: {
type: String,
required: true,
unique: true,
match: /^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$/
},
age: { type: Number, min: 18, max: 100 }
});
  • required: Ensures the field is not empty.
  • unique: Ensures no two documents have the same value for this field.
  • match: Validates the field based on a regular expression.
  • min/max: Validates numeric fields to ensure values fall within the specified range.

7. Mongoose Middleware

Mongoose supports middleware (also called hooks), which allows you to add custom logic before or after certain actions like saving, deleting, or updating a document.

Example: Pre-save Middleware

userSchema.pre('save', function(next) {
if (this.age < 18) {
throw new Error('Age must be at least 18');
}
next();
});

8. Relationships in Mongoose (Population)

Mongoose allows you to populate referenced documents from other collections, making it easy to implement relationships like one-to-many or many-to-many.

Example: One-to-Many Relationship

const postSchema = new mongoose.Schema({
title: String,
content: String,
author: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
});

const Post = mongoose.model('Post', postSchema);

Post.find().populate('author').exec((err, posts) => {
console.log(posts);
});

9. Best Practices for Mongoose

  • Schema Design: Design schemas to be as specific as possible, avoiding overly general models.
  • Indexes: Create indexes on fields you frequently query to optimize performance.
  • Error Handling: Always use try-catch or .catch() for error handling to handle MongoDB operation failures.
  • Validation: Use built-in Mongoose validation and custom validators for data integrity.
  • Middleware: Use Mongoose middleware for tasks like hashing passwords or updating timestamps.

10. Conclusion

Mongoose is an extremely powerful library for interacting with MongoDB in Node.js. It abstracts away many of the complexities of MongoDB and provides a user-friendly way to define schemas, perform CRUD operations, validate data, and manage relationships.

Today in History – 25 April

0
today in history 25 april

today in history 25 april

1859

At Port Said, Egypt, ground is broken for the Suez Canal, an artificial waterway intended to stretch 101 miles across the isthmus of Suez and connect the Mediterranean and the Red seas.

1955

Syed Mohammad Zamin Ali, great educationist, poet, editor, writer, professor and founder-member of the Hindustani Academy, passed away.

1969

Invalappil Mani Vijayan (or better known as IM Vijayan), Indian Soccer(Football) player, was born in Trissur, Kerala. He was recognised as Indian Player of the Year in 1993, 1997, 1999.

1982

India’s first telecast colour broadcasting started on Dordarshan.

1990

The crew of the U.S. space shuttle Discovery places the Hubble Space Telescope, a long-term space-based observatory, into a low orbit around Earth. The space telescope, conceived in the 1940s, designed in the 1970s, and built in the 1980s, was designed to give astronomers an unparalleled view of the solar system, the galaxy, and the universe.

1998

India protests against Pakistan raising the Kashmir issue at the first SAARC Information Ministers conference in Dhaka.

1998

The Government announces a new salary structure for university and college teachers, consequent to the implementation of the Fifth Pay Commission recommendations.

2000

The Supreme Court clears the decks for continuing the trial against AIADMK leader Jayalalitha in the controversial ”TANSI land deal case” by ”erasing” the Madras High Court judgment discharging her from the case.

2000

From a hideout in North 24 Parganas district, West Bengal police nabbed Belal alias Lalu Mian, the suspected mastermind behind the hijacking of IC-814 IA flight to Kandahar in December 1999.

Related Articles:

Today in History – 24 April

Today in History – 23 April

Today in History – 22 April

Today in History – 21 April

CRUD Operations in Node.js with MongoDB (with Code Examples)

0
mongodb course
mongodb course

Table of Contents

  1. Introduction
  2. What is CRUD?
  3. Setting Up the Project
  4. Connecting to MongoDB
  5. Create Operation (insertOne, insertMany)
  6. Read Operation (findOne, find)
  7. Update Operation (updateOne, updateMany)
  8. Delete Operation (deleteOne, deleteMany)
  9. Error Handling & Validation
  10. Organizing Code Structure
  11. Best Practices
  12. Conclusion

1. Introduction

MongoDB and Node.js are often paired together in modern web development due to their asynchronous capabilities and JSON-friendly nature. In this module, we’ll explore how to implement CRUD operations (Create, Read, Update, Delete) using the official MongoDB Node.js driver, not an ODM like Mongoose, giving you full control and transparency.


2. What is CRUD?

CRUD is an acronym for the four basic types of database operations:

  • Create – Add new data
  • Read – Retrieve data
  • Update – Modify existing data
  • Delete – Remove data

Each of these maps directly to methods provided by the MongoDB Node.js driver.


3. Setting Up the Project

Initialize Project

mkdir mongodb-crud-node
cd mongodb-crud-node
npm init -y
npm install mongodb dotenv

Setup .env File

MONGO_URI=mongodb://127.0.0.1:27017
DB_NAME=crud_demo

Folder Structure

.
├── .env
├── db.js
├── crud.js
└── index.js

4. Connecting to MongoDB

db.js

const { MongoClient } = require('mongodb');
require('dotenv').config();

const client = new MongoClient(process.env.MONGO_URI);
let db;

async function connectDB() {
if (!db) {
await client.connect();
db = client.db(process.env.DB_NAME);
console.log('Connected to MongoDB');
}
return db;
}

module.exports = connectDB;

5. Create Operation

insertOne

const db = await connectDB();
const users = db.collection('users');

await users.insertOne({
name: 'John Doe',
email: '[email protected]',
age: 30
});

insertMany

await users.insertMany([
{ name: 'Jane Doe', age: 25 },
{ name: 'Alice', age: 22 }
]);

6. Read Operation

findOne

const user = await users.findOne({ name: 'John Doe' });
console.log(user);

find + toArray

const userList = await users.find({ age: { $gt: 20 } }).toArray();
console.log(userList);

Add filters, projection, and sorting:

const usersSorted = await users.find({}, { projection: { name: 1, _id: 0 } }).sort({ age: -1 }).toArray();

7. Update Operation

updateOne

await users.updateOne(
{ name: 'John Doe' },
{ $set: { age: 31 } }
);

updateMany

await users.updateMany(
{ age: { $lt: 30 } },
{ $inc: { age: 1 } }
);

8. Delete Operation

deleteOne

await users.deleteOne({ name: 'John Doe' });

deleteMany

await users.deleteMany({ age: { $gt: 25 } });

9. Error Handling & Validation

Wrap each database interaction in try-catch to gracefully handle errors:

try {
const user = await users.insertOne({ name: 'Test' });
} catch (err) {
console.error('MongoDB Error:', err.message);
}

Use validation logic before making DB calls:

if (!email.includes('@')) throw new Error('Invalid email address');

You can also enforce schema validation using MongoDB 4.0+ features on the collection level.


10. Organizing Code Structure

To make your CRUD application production-ready:

Structure like:

/db
└── connect.js
/controllers
└── userController.js
/routes
└── userRoutes.js
index.js

Move each CRUD function to its own module in /controllers for clean separation.


11. Best Practices

  • Always close the connection in shutdown hooks.
  • Avoid hardcoded values – use environment variables.
  • Sanitize and validate user input.
  • Use appropriate indexes for frequent queries.
  • Prefer insertMany, updateMany, etc., for batch operations.
  • Keep the logic reusable by abstracting functions into services.
  • Use proper logging (e.g., Winston, Pino) in production.
  • Set a default limit on find() queries to avoid memory overload.

12. Conclusion

Implementing CRUD with the official MongoDB Node.js driver gives you low-level control over your database interactions. While tools like Mongoose abstract a lot, using the native driver teaches you how MongoDB works under the hood — a crucial skill for optimization, performance tuning, and working in microservices environments.