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 mongooseconst 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" } });
-