MongoDB and Mongoose Notes
Introduction to MongoDB
- Definition: MongoDB is an open-source NoSQL database that stores data in JSON-like documents (BSON).
- NoSQL vs SQL:
- NoSQL: Developed in late 2000s, focuses on scaling, fast queries, and flexible schemas.
- SQL: Developed in 1970s, focuses on reducing data duplication, has rigid schemas.
- Benefits of MongoDB:
- Flexible data models
- Horizontal scaling
- Fast queries
- Developer-friendly
- Terminology Comparison:
RDBMS MongoDB Table Collection Record Document Column Field Joins Embedded data
- MongoDB Atlas: Cloud-based database service for MongoDB.
Mongoose ODM
- Definition: Mongoose is an Object Data Modeling (ODM) library for MongoDB and Node.js.
- Installation and Setup:
To use Mongoose in your code:
npm install mongoose
const mongoose = require('mongoose');
-
Schema: Defines the structure of documents in a collection.
Example:
const companySchema = new Schema({ companyName: { type: String, unique: true }, address: String, phone: String, employeeCount: { type: Number, default: 0 }, country: String });
-
Model: Wrapper for the schema that provides an interface to the database.
let Company = mongoose.model('companies', companySchema);
- Connecting to MongoDB:
mongoose.connect('Your connection string here');
-
Unique Index: Enforces unique values for specific fields.
Example:
const userSchema = new Schema({ username: { type: String, unique: true }, email: String });
This ensures that no two documents can have the same
username
.
-
Recursive Schema: Allows nested structures of the same schema.
Example:
const commentSchema = new Schema({ text: String, author: String, date: { type: Date, default: Date.now } }); commentSchema.add({ replies: [commentSchema] });
This allows comments to have nested replies.
-
Multiple Connections: Possible to connect to multiple databases.
Example:
const conn1 = mongoose.createConnection('mongodb://localhost/db1'); const conn2 = mongoose.createConnection('mongodb://localhost/db2'); const Model1 = conn1.model('Model1', someSchema); const Model2 = conn2.model('Model2', anotherSchema);
This allows you to work with two different databases simultaneously.
CRUD Operations
- Create (Save):
const newCompany = new Company({ ... }); newCompany.save() .then(() => console.log("Saved")) .catch(err => console.log(err));
-
Read (Find):
Company.find({ companyName: 'The Kwik-E-Mart' }) .exec() .then(companies => console.log(companies)) .catch(err => console.log(err));
- Can select specific fields:
Company.find({}, 'address phone')
- Can select specific fields:
- Update:
Company.updateOne({ companyName: 'The Kwik-E-Mart' }, { $set: { employeeCount: 3 } }) .exec() .then(() => console.log('Updated')) .catch(err => console.log(err));
- Delete:
Company.deleteOne({ companyName: 'The Kwik-E-Mart' }) .exec() .then(() => console.log('Deleted')) .catch(err => console.log(err));
Best Practices
- Use
.exec()
after queries to return a proper promise.
-
Encode passwords with special characters using
encodeURIComponent()
.Example:
const password = "p@ssw0rd!"; const encodedPassword = encodeURIComponent(password); const connectionString = `mongodb+srv://username:${encodedPassword}@cluster0.example.net/mydb`; mongoose.connect(connectionString);
This ensures that special characters in the password don't interfere with the connection string.
- Handle errors properly in all database operations.
-
Use appropriate update operators like
$set
,$push
, and$addToSet
.Definition: Update operators are special keys that you can use to modify data in specific ways.
Examples:
-
$set
: Sets the value of a field.Company.updateOne({ name: "Acme Inc" }, { $set: { employees: 100 } });
-
$push
: Adds an element to an array field.User.updateOne({ username: "john" }, { $push: { hobbies: "painting" } });
-
$addToSet
: Adds an element to an array field only if it doesn't already exist.User.updateOne({ username: "john" }, { $addToSet: { tags: "developer" } });
-