Mongodb Theory
Mongodb Theory
MongoDB Basics
o What is MongoDB ?
1. MongoDB is an open-source NoSQL database.
2. Document-based and cross-platform compatible.
3. Offers high performance and high availability.
4. Supports easy scalability for large data handling.
5. Differs from relational databases by using a flexible, schema-less data
model.
6. Built on BSON (Binary JSON), allowing for efficient storage and
querying of non-structured data.
o Key Features of MongoDB ?
1. Document-oriented: MongoDB stores data in JSON-like documents
(BSON format). The flexible data model adapts to real-world object
representations.
2. Scalability: Offers automatic scaling. Can scale horizontally by
sharding (partitioning data across servers) and vertically by adding
storage.
3. Indexing: Supports indexing on any document attribute to enhance
query performance.
4. Replication: Provides high availability through replica sets. Primary
and secondary nodes maintain data copies.
5. Aggregation: Features a powerful aggregation framework. Enables
complex data operations like transformations, filtering, and sorting.
6. Ad hoc queries: Supports searching by field, range, and regular
expressions.
o When we Use MongoDB ?
1. Content Management Systems (CMS): MongoDB’s dynamic schema
efficiently supports various content types, making it ideal for CMS
needs.
2. E-Commerce Platforms: With its scalability and flexibility,
MongoDB handles complex product catalogs, customer data, and
orders seamlessly.
3. Social Networks: Designed to store large volumes of posts, user
profiles, and interactions, MongoDB is well-suited for social media
platforms.
4. Real-Time Analytics: Equipped with aggregation and indexing,
MongoDB enables the analysis and processing of live data for
actionable insights.
5. IoT Applications: MongoDB’s flexible data model captures and stores
data from countless devices and sensors, a key requirement in IoT
applications.
6. Gaming: MongoDB manages player profiles, game progress, and other
real-time data needed for a responsive gaming experience.
7. Location-Based Services: With robust geospatial capabilities,
MongoDB efficiently handles map data, locations, and geolocation
queries.
8. Big Data: MongoDB’s flexible model and horizontal scalability make
it ideal for managing vast amounts of unstructured and semi-structured
data.
9. Mobile Applications: The flexible data model in MongoDB adapts
well to the evolving data types and dynamic nature of mobile apps.
o MongoDB Terminology ?
1. Database: Holds collections and structures needed to manage data.
2. Collection: A group of related documents, like a table in traditional
databases.
3. Document: A single record in a collection, made up of fields.
Documents don’t need a fixed structure.
4. Field: A piece of data in a document, similar to a column in a table.
5. Index: A structure that speeds up searches, making data retrieval
faster.
6. Query: A way to get specific data from a collection based on
conditions.
7. Cursor: A pointer to the query result set, enabling efficient processing
of individual documents.
8. Aggregation: Summarizes and transforms data in collections for
complex analysis or report generation.
9. Replica Set: A group of MongoDB instances with the same data,
providing redundancy, high availability, and automatic failover.
10. Sharding: Distributes data across multiple machines to scale
horizontally, breaking the dataset into manageable chunks called
shards.
o MongoDB Compass vs MongoDB Atlas
1. MongoDB Compass
2. MongoDB Atlas
Schema-based Validation
With Mongoose, you create a schema to define the rules for your data.
For example, you can specify:
Model-based Queries
Once you define the schema, you create a model. This model helps
you interact with the data in your MongoDB collection (e.g., adding,
finding, updating, or deleting data).
Adding Data: .save()
Finding Data: .find(), .findOne()
Updating Data: .updateOne()
Deleting Data: .deleteOne()
Middleware (Hooks)
Mongoose lets you run custom logic before or after certain actions.
For example:
userSchema.pre('save', function(next) {
console.log('Saving user:', this.name);
next(); // Proceed to save the document.
});
Population
Mongoose lets you link data from different collections. For example,
you can link a User with their Posts. This is called population.
User.findOne({ name:
'Alice' }).populate('posts').then(user =>
console.log(user));
Query Building
Aggregation
o Mongo export
o mongodump
mongodump is a MongoDB utility for creating database backups.
Exports data into BSON (Binary JSON) format.
Can back up entire databases or specific collections.
Default output directory is ./dump (can be changed with -out).
Use mongorestore to restore the backup.
Basic Usage:
mongodump --uri <MongoDB connection string>
Common Use Cases:
mongorestore /path/to/backup
o SQL vs NoSQL
SQL
BSON (Binary JSON) is the format MongoDB uses to store data. In addition
to standard JSON types, BSON supports:
Date
0.
Stores dates as milliseconds since the Unix epoch.
1. Binary Data
Stores binary content like images, videos, or files.
2. ObjectId
Unique 12-byte identifier automatically generated for each
document.
3. Decimal128
High-precision decimal type for monetary or scientific
calculations.
4. Code
Stores JavaScript code within documents.
5. Regular Expression
Stores regex patterns directly in documents.
6. MinKey/MaxKey
Special types to compare values in a query.
Embedded Documents and Arrays
You can easily query embedded arrays using MongoDB’s array query
operators, like $elemMatch, **$all**, and **$size**. You can also use dot
notation to search and update embedded documents.
Example Query:
{
"addressId": 101,
"street": "123 Main St",
"city": "Springfield"
}
Advantages:
No size limits.
Better for frequently updated data.
Disadvantages:
Slower reads (requires additional queries).
More complex queries.
Data Model and Data Types
In MongoDB, data is stored in BSON format, which supports various data types.
Knowing these types is important for effective schema design and query performance.
0. countDocuments()
2. estimatedDocumentCount()
3. count()
How to Use It
Example:
Output
Performance Note
Using full can slow down your database, so use it carefully on large
collections.
o What is a Cursor?
A cursor is like a pointer that allows you to go through the results of a
query one document at a time.
In MongoDB, a cursor acts as a pointer to the documents in a
collection, and it allows you to retrieve documents one at a time.
When you ask MongoDB for documents, it gives you a cursor to help
you retrieve them.
Creating a Cursor: When you run a query (like finding documents),
MongoDB automatically creates a cursor.
const cursor = db.collection('myCollection').find();
Iterating Through Documents: You can loop through the results using
the forEach method:
cursor.forEach((doc) => {
console.log(doc); // This prints each document to the
console
});
Cursor Methods
const cursor = db
.collection('myCollection')
.find({ age: { $gt: 25 } })
.sort('name', 1)
.limit(10)
.skip(20)
.project({ name: 1, _id: 0 });
Closing Cursor
In MongoDB, you use collections to store documents. To add data, you can
use two main methods: insertOne() and insertMany().
db.collection.insertMany([
{ name: 'Ai', age: 20 },
{ name: 'Ash', age: 21 },
{ name: 'Messi', age: 35 }
]);
o find()
The find() method is used to search for documents within a collection. You
can filter, sort, and limit the results based on your needs.
2. Query Filters
3. Logical Operators
Use logical operators like $and, $or, and $not for complex queries.
db.users.find({ $and: [{ age: 25 }, { first_name:
'John' }] }); // Finds users who are 25 and named John
4. Projection
5. Sorting
The _id field is a unique identifier for each MongoDB document. Its default value is
an ObjectId, which has the following structure:
Example of an ObjectId:
64d7f9e1d8347a12cfc1b032
OPERATORS
o Comparison Operators
$eq (Equal)
Checks if two values are equal; returns true if they are, otherwise
false.
Syntax
{ field: { $nin: [<value1>, <value2>, ..., <valueN>]
} }
Example
[
{ _id: 1, title: 'The Silent Patient', genre:
'Mystery' },
{ _id: 2, title: 'Dune', genre: 'Sci-Fi' },
{ _id: 3, title: 'Educated', genre:
'Biography' },
{ _id: 4, title: 'The Alchemist', genre:
'Adventure' },
{ _id: 5, title: 'The Great Gatsby' }
]
Summary
$in
Syntax
{ field: { $in: [<value1>, <value2>, ...] } }
Example
[
{ _id: 1, title: 'MongoDB', tags: ['database',
'NoSQL'] },
{ _id: 2, title: 'Node.js', tags: ['javascript',
'runtime'] },
{ _id: 3, title: 'React', tags: ['NoSQL',
'javascript'] },
{ _id: 4, title: 'React', tags: ['SQL',
'React'] },
{ _id: 5, title: 'React', tags: ['React',
'MySQL'] },
]
Result:
[
{ _id: 1, title: 'MongoDB', tags:
['database', 'NoSQL'] },
{ _id: 2, title: 'Node.js', tags:
['javascript', 'runtime'] },
{ _id: 3, title: 'React', tags: ['NoSQL',
'javascript'] }
]
Summary
The $in operator lets you check if a field’s value exists within
a specified list of values, which is useful for filtering multiple
possible matches.
o Logical Operators
$and
Syntax:
{ $and: [{ condition1 }, { condition2 }, ... ] }
Example: Find orders with a price greater than 1 and quantity
less than 10:
db.orders.find({ $and: [{ price: { $gt: 1 } },
{ quantity: { $lt: 10 } }] });
Results:
{ "_id": 3, "item": "orange", "price": 2,
"quantity": 5 }
Note
You can also achieve the same result without using $and:
$or
The $or operator allows you to query multiple conditions and returns
documents that satisfy any of the specified conditions.
Syntax:
{
$or: [
{ condition1 },
{ condition2 },
// ...,
{ conditionN }
]
}
Example: Find products where the category is "Fruits" or the
price is less than or equal to 15:
db.products.find({
$or: [
{ category: 'Fruits' },
{ price: { $lte: 15 } }
]
});
Results:
[
{ _id: 1, category: 'Fruits', price: 20 },
{ _id: 2, category: 'Fruits', price: 30 },
{ _id: 3, category: 'Vegetables', price: 10
},
{ _id: 4, category: 'Vegetables', price: 15
}
]
To find documents where the category is "Fruits" and
the price is either less than 20 or greater than 25:
db.products.find({
$and: [
{ category: 'Fruits' },
{
$or: [
{ price: { $lt: 20 } },
{ price: { $gt: 25 } }
]
}
]
});
Results:
[{ _id: 2, category: 'Fruits', price: 30 }]
$not
Syntax:
{
field: { $not: { <operator-expression> } }
}
Examples
Syntax
{ $nor: [ { <condition1> },
{ <condition2> }, ... ] }
Example
[
{ _id: 1, name: 'Alice', age: 30, subjects:
['math', 'science'] },
{ _id: 2, name: 'Bob', age: 25, subjects:
['history'] },
{ _id: 3, name: 'Cathy', age: 35, subjects:
['math', 'history'] },
{ _id: 4, name: 'David', age: 28, subjects:
['science'] },
]
Query
Find students who are not older than 30 and not studying math:
db.students.find({
$nor: [{ age: { $gt: 30 } }, { subjects:
'math' }],
});
Result:
[
{ _id: 2, name: 'Bob', age: 25, subjects:
['history'] },
{ _id: 4, name: 'David', age: 28, subjects:
['science'] }
]
o Array Operators
$all
Syntax
{
<field>: {
$all: [<value1>, <value2>, ..., <valueN>]
}
}
Example
To find all movies with both the "action" and "sci-fi" tags:
Result:
[
{ _id: 1, title: "The Matrix", tags:
["action", "sci-fi", "cyberpunk"] },
{ _id: 2, title: "Inception", tags:
["action", "thriller", "sci-fi"] }
]
Summary
$elemMatch
The $elemMatch operator checks which object in the array meets the
specified conditions in the query. dealing with arrays of objects
Syntax
{
<field>: {
$elemMatch: { <condition1>, <condition2>, ...,
<conditionN> }
}
}
Example
[
{ _id: 1, student: "Mary", grades: [{ subject:
"Math", score: 80 }, { subject: "English", score:
75 }] },
{ _id: 2, student: "Tom", grades: [{ subject:
"Math", score: 90 }, { subject: "English", score:
80 }] },
{ _id: 3, student: "John", grades: [{ subject:
"Math", score: 85 }, { subject: "English", score:
65 }] },
{ _id: 4, student: "Lucy", grades: [{ subject:
"Math", score: 70 }, { subject: "English", score:
85 }] }
]
Query
db.courseRecords.find({
grades: {
$elemMatch: {
subject: "Math",
score: { $gte: 80 }
}
}
});
Explanation of Query
[
{ _id: 1, student: "Mary", grades:
[{ subject: "Math", score: 80 }, { subject:
"English", score: 75 }] },
{ _id: 2, student: "Tom", grades:
[{ subject: "Math", score: 90 }, { subject:
"English", score: 80 }] },
{ _id: 3, student: "John", grades:
[{ subject: "Math", score: 85 }, { subject:
"English", score: 65 }] }
]
Result Explanation
Syntax
{ "<array_field>": { "$size": <number_of_elements> }
}
<array_field>: The name of the array field you want
to check.
<number_of_elements>: The exact number of
elements you want to match.
Example
[
{ "_id": 1, "name": "Shirt", "colors": ["red",
"blue", "green"] },
{ "_id": 2, "name": "Pants", "colors": ["black",
"white", "grey", "blue", "red"] },
{ "_id": 3, "name": "Hat", "colors": ["yellow"] }
]
To find all products that have exactly 5 colors, you would use
the following query:
Result
[
{ "_id": 2, "name": "Pants", "colors":
["black", "white", "grey", "blue", "red"] }
]
Important Notes
The $size operator matches documents that
have an exact number of elements in the
specified array field.
For more flexible array length comparisons
(e.g., greater than or less than), you might need
to use $expr along with $size in the
aggregation framework.
The $size operator does not require an
additional index for efficiency; it can utilize
existing indexes on the array field.
o Element Operators
$exists
Syntax
{ "field": { "$exists": <boolean> } }
Example
[
{ "_id": 1, "title": "MongoDB Basics", "author":
"John Doe" },
{ "_id": 2, "title": "Advanced MongoDB",
"published": 2022 },
{ "_id": 3, "title": "JavaScript", "author": "Jan
Smit", "edition": null }
]
The $type operator is used to filter documents based on the data type
of a specified field. It allows you to query for documents that have
fields of a certain BSON data type.
Syntax
{
fieldName: {
$type: dataType
}
}
fieldName: The name of the field you want to check.
dataType: The BSON data type or its corresponding
alias.
Common BSON Data Types and Aliases
Type Alias
Double 1 or "double"
String 2 or "string"
Object 3 or "object"
Array 4 or "array"
Binary 5 or "binData"
ObjectId 7 or "objectId"
Boolean 8 or "bool"
Date 9 or "date"
Null 10 or "null"
Int32 16 or "int"
Int64 18 or "long"
Decimal128 19 or "decimal"
Example
[
{ "_id": 1, "name": "Laptop", "price": 999.99,
"inStock": true },
{ "_id": 2, "name": "Smartphone", "price":
599.99, "inStock": true },
{ "_id": 3, "name": "Tablet", "price": "300",
"inStock": "yes" }, // price is a string
{ "_id": 4, "name": "Headphones", "price": null,
"inStock": false },
{ "_id": 5, "name": "Monitor", "price": 250.00,
"inStock": true }
]
Result:
[
{ "_id": 1, "name": "Laptop",
"price": 999.99, "inStock": true },
{ "_id": 2, "name": "Smartphone",
"price": 599.99, "inStock": true },
{ "_id": 5, "name": "Monitor",
"price": 250.00, "inStock": true }
]
Result:
[
{ "_id": 3, "name": "Tablet",
"price": "300", "inStock": "yes" }
]
Result:
[
{ "_id": 4, "name": "Headphones",
"price": null, "inStock": false }
]
Summary
Syntax:
db.collection.find({
$expr: { $gt: ["$field1", "$field2"] }
});
Example Find documents where field1 is greater than field2
[
{ "_id": 1, "field1": 10, "field2": 5 },
{ "_id": 2, "field1": 3, "field2": 8 },
{ "_id": 3, "field1": 15, "field2": 15 }
]
Query:
db.collection.find({
$expr: { $gt: ["$field1", "$field2"] }
});
Result:
[
{ "_id": 1, "field1": 10, "field2": 5 }
]
Conclusion
$regex
Syntax
0. /al/:
Result
[
{ "_id": 1, "name": "Alice Johnson" }
]
Case-Insensitive Search:
db.users.find({ name: { $regex: 'alice',
$options: 'i' } });
Result
[
{ "_id": 1, "name": "Alice Johnson" }
]
Result
[]
Summary
The $regex operator allows you to search for patterns in text
fields, making it a useful tool for flexible querying in
MongoDB.
$jsonSchema
Syntax:
db.collection.find({
$jsonSchema: {
bsonType: "object",
required: ["name", "age"],
properties: {
name: { bsonType: "string" },
age: { bsonType: "int", minimum: 18 }
}
}
});
Example
[
{ "_id": 1, "name": "Alice", "age": 30 },
{ "_id": 2, "name": "Bob", "age": 17 },
{ "_id": 3, "name": "Charlie", "age": 22 }
]
Query
Result:
[
{ "_id": 1, "name": "Alice", "age": 30 },
{ "_id": 3, "name": "Charlie", "age": 22 }
]
Conclusion
$mod
Syntax:
db.collection.find({
field: { $mod: [divisor, remainder] }
});
Example
[
{ "_id": 1, "number": 10 },
{ "_id": 2, "number": 15 },
{ "_id": 3, "number": 20 }
]
Query
Result:
[
{ "_id": 1, "number": 10 },
{ "_id": 3, "number": 20 }
]
Conclusion
$text
Syntax:
db.collection.find({
$text: { $search: "some text" }
});
Example
[
{ "_id": 1, "content": "Learn MongoDB basics" },
{ "_id": 2, "content": "Advanced MongoDB
techniques" },
{ "_id": 3, "content": "JavaScript programming" }
]
Query
Result:
[
{ "_id": 1, "content": "Learn MongoDB
basics" },
{ "_id": 2, "content": "Advanced MongoDB
techniques" }
]
Conclusion
$where
Syntax:
db.collection.find({
$where: "this.field > value"
});
Example
[
{ "_id": 1, "value": 10 },
{ "_id": 2, "value": 20 },
{ "_id": 3, "value": 30 }
]
Query
Result:
[
{ "_id": 2, "value": 20 },
{ "_id": 3, "value": 30 }
]
Conclusion
o Update Operators
$set: Sets the value of a field in a document.
Example Document:
{ "_id": 1, "name": "Alice", "age": 25 }
Query:
db.users.updateOne(
{ _id: 1 },
{ $set: { age: 30 }}
);
Result:
{ "_id": 1, "name": "Alice", "age": 30 }
$unset: Removes a field from a document.
Example Document:
{ "_id": 1, "name": "Alice", "email":
"[email protected]" }
Query:
db.users.updateOne(
{ _id: 1 },
{ $unset: { email: "" }}
);
Result:
{ "_id": 1, "name": "Alice" }
$inc: Increments the value of a field by a specified amount.
Example Document:
{ "_id": 1, "name": "Alice", "age": 30 }
Query:
db.users.updateOne(
{ _id: 1 },
{ $inc: { age: 1 }}
);
Result:
{ "_id": 1, "name": "Alice", "age": 31 }
**$push**: Adds an element to an array field.
Example Document:
{ "_id": 1, "name": "Alice", "hobbies":
["Reading"] }
Query:
db.users.updateOne(
{ _id: 1 },
{ $push: { hobbies: "Cooking" }}
);
Result:
{ "_id": 1, "name": "Alice", "hobbies": ["Reading",
"Cooking"] }
$addToSet: Adds a value to an array only if it doesn't already exist in
the array.
Example Document:
{
"_id": 1,
"name": "Alice",
"hobbies": ["Reading", "Cycling", "Swimming"]
}
Query:
Now, if we try to add "Swimming" again using $addToSet,
we would run:
db.users.updateOne(
{ _id: 1 }, // Find the
document with _id equal to 1
{ $addToSet: { hobbies: "Swimming" }} // Try to
add "Swimming" to the hobbies array
);
Result:
{
"_id": 1,
"name": "Alice",
"hobbies": ["Reading", "Cycling", "Swimming"]
}
$pop: Removes the first or last element of an array.
Example Document:
{ "_id": 1, "name": "Alice", "hobbies": ["Reading",
"Cooking"] }
Query:
db.users.updateOne(
{ _id: 1 },
{ $pop: { hobbies: 1 }}
);
Result:
{ "_id": 1, "name": "Alice", "hobbies":
["Reading"] }
$pull: Removes all instances of a value from an array.
Example Document:
{ "_id": 1, "name": "Alice", "hobbies": ["Reading",
"Cooking"] }
Query:
db.users.updateOne(
{ _id: 1 },
{ $pull: { hobbies: "Reading" }}
);
Result:
{ "_id": 1, "name": "Alice", "hobbies":
["Cooking"] }
$rename: Renames a field.
Example Document:
{ "_id": 1, "name": "Alice", "age": 25 }
Query:
db.users.updateOne(
{ _id: 1 },
{ $rename: { name: "fullName" }}
);
Result:
{ "_id": 1, "fullName": "Alice", "age": 25 }
o Projection Operators
$project
Syntax
{ $project: { field1: <value>, field2:
<value>, ... } }
field1, field2: Names of the fields to include (1) or
exclude (0).
Example
{
"_id": 1,
"name": "John Doe",
"age": 30,
"email": "[email protected]"
}
Query:
db.users.aggregate([
{
$project: {
name: 1,
email: 0 // Exclude email
}
}
]);
Result
{
"_id": 1,
"name": "John Doe"
}
$include
Syntax
{ field: 1 }
field: The name of the field to include.
1: Indicates that the field should be included in the
results.
Example
[
{
"title": "The Catcher in the Rye",
"author": "J.D. Salinger",
"year": 1951,
"genre": "Literary fiction"
},
{
"title": "To Kill a Mockingbird",
"author": "Harper Lee",
"year": 1960,
"genre": "Southern Gothic"
},
{
"title": "Of Mice and Men",
"author": "John Steinbeck",
"year": 1937,
"genre": "Novella"
}
]
Query:
Result
[
{
"title": "The Catcher in the Rye",
"author": "J.D. Salinger"
},
{
"title": "To Kill a Mockingbird",
"author": "Harper Lee"
},
{
"title": "Of Mice and Men",
"author": "John Steinbeck"
}
]
Note
Syntax
{
$project: {
field1: 0,
field2: 0,
...
}
}
Example
Suppose we have a collection called students with the
following documents:
[
{ "_id": 1, "name": "John Doe", "age": 20,
"course": "Software Engineering" },
{ "_id": 2, "name": "Jane Smith", "age": 22,
"course": "Computer Science" },
{ "_id": 3, "name": "Richard Roe", "age": 21,
"course": "Information Technology" }
]
If you want to fetch all the students but exclude the age field
from the result, you can use the following command:
db.students.aggregate([
{
$project: {
age: 0 // Exclude the age field
}
}
]);
Result
[
{ "_id": 1, "name": "John Doe", "course":
"Software Engineering" },
{ "_id": 2, "name": "Jane Smith", "course":
"Computer Science" },
{ "_id": 3, "name": "Richard Roe",
"course": "Information Technology" }
]
Important Note
$slice
Syntax
0. Limit number of elements:
1. { field: { $slice: <number> } }
2. Limit from a specific position:
3. { field: { $slice: [<skip>, <limit>] } }
Examples
Document:
{
"_id": 1,
"title": "My First Post",
"tags": ["mongodb", "database", "nosql",
"backend"]
}
Query:
Result:
{
"_id": 1,
"tags": ["mongodb", "database",
"nosql"]
}
Document:
{
"_id": 2,
"title": "My Second Post",
"tags": ["mongodb", "database", "nosql",
"backend", "development", "coding"]
}
Query:
Result:
{
"_id": 2,
"tags": ["development", "coding"]
}
Conclusion
The $slice operator is a simple way to limit the number of
array items returned in MongoDB queries.
A bulk write operation allows you to perform multiple write operations (insert,
update, replace, or delete) in a single command for better performance and
reduced network overhead.
Syntax:
db.collection.bulkWrite([
{ insertOne: { document: { /* document fields
*/ } } },
{ updateOne: { filter: { /* filter criteria */ },
update: { /* update fields */ } } },
{ deleteOne: { filter: { /* filter criteria */ } } },
// Additional operations...
])
Example:
Collection: products
[
{ "_id": 1, "name": "Laptop", "price": 1200 },
{ "_id": 2, "name": "Phone", "price": 800 },
{ "_id": 3, "name": "Tablet", "price": 400 }
]
Summary:
The bulk write operation efficiently performs multiple write operations
in a single call, improving performance and reducing the number of
network requests.
o Accumulator Operators
Query:
db.transactions.aggregate([
{ $group: { _id: "$category", totalAmount:
{ $sum: "$amount" } } }
])
Result:
[
{ "_id": "Stationery", "totalAmount":
22 },
{ "_id": "Fruit", "totalAmount": 1 }
]
$avg: Calculates the average of numeric values in a group.
Syntax: { $avg: "<field>" }
Example Collection: sales
[
{ "_id": 1, "product": "Laptop", "price": 1200,
"category": "Electronics" },
{ "_id": 2, "product": "Phone", "price": 800,
"category": "Electronics" },
{ "_id": 3, "product": "Tablet", "price": 600,
"category": "Electronics" }
]
Query:
db.sales.aggregate([
{ $group: { _id: "$category", averagePrice:
{ $avg: "$price" } } }
])
Result:
[
{ "_id": "Electronics", "averagePrice":
866.67 }
]
$min: Finds the minimum value in a group.
Syntax: { $min: "<field>" }
Example Collection: grades
[
{ "_id": 1, "student": "Alice", "score": 85,
"subject": "Math" },
{ "_id": 2, "student": "Bob", "score": 75,
"subject": "Math" },
{ "_id": 3, "student": "Charlie", "score": 90,
"subject": "Math" }
]
Query:
db.grades.aggregate([
{ $group: { _id: "$subject", minScore: { $min:
"$score" } } }
])
Result:
[
{ "_id": "Math", "minScore": 75 }
]
$max: Finds the maximum value in a group.
Syntax: { $max: "<field>" }
Example Collection: products
[
{ "_id": 1, "name": "TV", "price": 500 },
{ "_id": 2, "name": "Laptop", "price": 1200 },
{ "_id": 3, "name": "Phone", "price": 800 }
]
Query:
db.products.aggregate([
{ $group: { _id: null, maxPrice: { $max:
"$price" } } }
])
Result:
[
{ "_id": null, "maxPrice": 1200 }
]
$first:Returns the first value in a group based on the order of
documents.
Syntax: { $first: "<field>" }
Example Collection: orders
[
{ "_id": 1, "customer": "Alice", "amount": 200,
"date": "2024-01-01" },
{ "_id": 2, "customer": "Bob", "amount": 150,
"date": "2024-02-01" },
{ "_id": 3, "customer": "Charlie", "amount":
300, "date": "2024-03-01" }
]
Query:
db.orders.aggregate([
{ $group: { _id: null, firstOrder: { $first:
"$customer" } } }
])
Result:
[
{ "_id": null, "firstOrder": "Alice" }
]
$last:Returns the last value in a group based on the order of
documents.
Syntax: { $last: "<field>" }
Example Collection: employees
[
{ "_id": 1, "name": "Alice", "department": "HR",
"joined": "2023-01-01" },
{ "_id": 2, "name": "Bob", "department": "HR",
"joined": "2023-02-01" },
{ "_id": 3, "name": "Charlie", "department":
"HR", "joined": "2023-03-01" }
]
Query:
db.employees.aggregate([
{ $group: { _id: "$department", lastJoined:
{ $last: "$name" } } }
])
Result:
[
{ "_id": "HR", "lastJoined": "Charlie" }
]
$push: Creates an array with all values from a specified field in a
group.
Syntax: { $push: "<field>" }
Example Collection: inventory
[
{ "_id": 1, "product": "Apple", "category":
"Fruit" },
{ "_id": 2, "product": "Orange", "category":
"Fruit" },
{ "_id": 3, "product": "Banana", "category":
"Fruit" }
]
Query:
db.inventory.aggregate([
{ $group: { _id: "$category", allProducts:
{ $push: "$product" } } }
])
Result:
[
{ "_id": "Fruit", "allProducts":
["Apple", "Orange", "Banana"] }
]
$addToSet: Creates an array of unique values from a specified field in
a group.
Syntax: { $addToSet: "<field>" }
Example Collection: purchases
[
{ "_id": 1, "product": "Apple", "category":
"Fruit" },
{ "_id": 2, "product": "Apple", "category":
"Fruit" },
{ "_id": 3, "product": "Banana", "category":
"Fruit" }
]
Query:
db.purchases.aggregate([
{ $group: { _id: "$category", uniqueProducts: {
$addToSet: "$product" } } }
])
Result:
[
{ "_id": "Fruit", "uniqueProducts":
["Apple", "Banana"] }
]
o Upsert Option
Syntax
db.collection.updateOne(
{ filterCriteria },
{ updateOperations },
{ upsert: true }
)
Example
[
{ "_id": 1, "name": "Laptop", "price": 1200 }
]
If we try to update a document with a filter that doesn’t match any
existing documents, upsert will insert a new document.
Query:
db.products.updateOne(
{ name: "Phone" },
{ $set: { price: 800 } },
{ upsert: true }
)
Result: Since no document with name: "Phone" exists,
MongoDB inserts a new document:
{ "_id": ObjectId(...), "name": "Phone", "price":
800 }
Summary
The upsert option is useful when you want to either update existing
documents or insert a new one if no matches are found in the
collection.
Syntax
{ $match: { <query> } }
Example
[
{ "_id": 1, "firstName": "John", "age": 25,
"department": "HR" },
{ "_id": 2, "firstName": "Jane", "age": 35,
"department": "Finance" },
{ "_id": 3, "firstName": "Mike", "age": 28,
"department": "HR" }
]
Query:
db.employees.aggregate([
{ $match: { age: { $gt: 30 } } }
])
Result
[
{ "_id": 2, "firstName": "Jane", "age": 35,
"department": "Finance" }
]
This result shows only the employee who is older than 30.
Syntax
{
$group: {
_id: <expression>,
<field1>: { <accumulator1>: <expression1> },
...
}
}
_id: The field or expression used to group the documents.
<field1>: The name of the new field in the result that will hold
computed values.
<accumulator1>: An accumulator operator (e.g., $sum, $avg,
$max, $min) that defines the calculation to perform.
<expression1>: The field or expression to which the
accumulator applies.
Example
db.orders.aggregate([
{
$group: {
_id: "$customer_id",
total_spent: { $sum: "$amount" }
}
}
])
Result
[
{ "_id": "C1", "total_spent": 200 },
{ "_id": "C2", "total_spent": 200 },
{ "_id": "C3", "total_spent": 200 }
]
The $sort operator in MongoDB is used to sort documents that pass through
the aggregation pipeline based on specified field(s) in either ascending or
descending order.
Syntax
{ $sort: { field1: <sort order>, field2: <sort
order>, ... } }
field1, field2: The fields by which you want to sort the
documents.
<sort order>: Use 1 for ascending order and 1 for descending
order.
Examples
[
{ "_id": 1, "name": "Alice", "age": 22 },
{ "_id": 2, "name": "Bob", "age": 25 },
{ "_id": 3, "name": "Charlie", "age": 20 }
]
Result:
[
{ "_id": 3, "name": "Charlie", "age": 20 },
{ "_id": 1, "name": "Alice", "age": 22 },
{ "_id": 2, "name": "Bob", "age": 25 }
]
2: Sorting by Age in Descending Order
Result:
[
{ "_id": 2, "name": "Bob", "age": 25 },
{ "_id": 1, "name": "Alice", "age": 22 },
{ "_id": 3, "name": "Charlie", "age": 20 }
]
3: Sorting by Multiple Fields
Result:
[
{ "_id": 2, "name": "Bob", "age": 25 },
{ "_id": 1, "name": "Alice", "age": 22 },
{ "_id": 3, "name": "Charlie", "age": 20 }
]
Important Note
Syntax
{ $project: { field1: <value>, field2: <value>, ... } }
field1, field2: Names of the fields to include (1) or exclude (0).
Example
{
"_id": 1,
"name": "John Doe",
"age": 30,
"email": "[email protected]"
}
Query:
db.users.aggregate([
{
$project: {
name: 1,
email: 0 // Exclude email
}
}
]);
Result
{
"_id": 1,
"name": "John Doe"
}
This query returns documents that only include the name field
and exclude the email field.
Syntax
{ $skip: <number> }
<number>: The number of documents to skip.
Example
[
{ "_id": 1, "name": "John", "age": 28 },
{ "_id": 2, "name": "Jane", "age": 32 },
{ "_id": 3, "name": "Bob", "age": 25 },
{ "_id": 4, "name": "Alice", "age": 30 },
{ "_id": 5, "name": "Charlie", "age": 27 },
{ "_id": 6, "name": "Diana", "age": 29 }
]
db.employees.aggregate([
{ $skip: 3 }
])
Result:
[
{ "_id": 4, "name": "Alice", "age": 30 },
{ "_id": 5, "name": "Charlie", "age": 27 },
{ "_id": 6, "name": "Diana", "age": 29 }
]
Important Notes
Order Matters: The $skip operator does not guarantee the
order of documents passed through it, so it's recommended to
use $sort before $skip if the order is important.
Performance Consideration: For better performance, consider
combining $skip with additional filters and placing it later in
the aggregation pipeline.
o $limit Limits result count.
The $limit operator restricts the number of documents that are passed to the
next stage in the aggregation pipeline. It is particularly useful for debugging
and controlling the output of queries.
Syntax
{ $limit: <number> }
<number>: The maximum number of documents to return.
Example
[
{ "_id": 1, "name": "John", "age": 28 },
{ "_id": 2, "name": "Jane", "age": 32 },
{ "_id": 3, "name": "Bob", "age": 25 },
{ "_id": 4, "name": "Alice", "age": 30 },
{ "_id": 5, "name": "Charlie", "age": 27 },
{ "_id": 6, "name": "Diana", "age": 29 }
]
db.employees.aggregate([
{ $limit: 3 }
])
Result:
[
{ "_id": 1, "name": "John", "age": 28 },
{ "_id": 2, "name": "Jane", "age": 32 },
{ "_id": 3, "name": "Bob", "age": 25 }
]
Important Notes
Syntax
{ $sum: <expression> }
Example
[
{ "_id": 1, "total": 50 },
{ "_id": 2, "total": 100 },
{ "_id": 3, "total": 150 }
]
Objective
You want to calculate the total sum of the total field across all
documents in the orders collection.
Aggregation Query
db.orders.aggregate([
{
$group: {
_id: null, // No specific grouping, we want the
total for all documents
totalSum: { $sum: "$total" } // Sum the 'total'
field
}
}
]);
Result
[
{
"_id": null,
"totalSum": 300
}
]
Explanation
$group: Combines the documents into a single output
document.
totalSum: The new field in the output that contains the
sum of the total field from all documents.
$sum: "$total": Calculates the sum of the total
field.
When you use the $unwind operator in MongoDB on an array that contains
multiple objects, it will return each object in the array as a separate document.
This allows you to work with each object individually, which is useful for
analysis or manipulation of the data.
Syntax
{
$unwind: {
path: "<arrayField>",
includeArrayIndex: "<string>", // Optional
preserveNullAndEmptyArrays: <boolean> // Optional
}
}
path: The field path of the array you want to unwind (prefixed
with $).
includeArrayIndex: (Optional) Adds the index of the array
element.
preserveNullAndEmptyArrays: (Optional) If true, includes
documents with no array.
Example
{
"_id": 1,
"item": "itemA",
"orders": [
{ "quantity": 2, "unitPrice": 10 },
{ "quantity": 3, "unitPrice": 20 }
]
}
Using $unwind:
db.sales.aggregate([
{ $unwind: { path: "$orders" } }
])
Result:
[
{ "_id": 1, "item": "itemA", "orders":
{ "quantity": 2, "unitPrice": 10 } },
{ "_id": 1, "item": "itemA", "orders":
{ "quantity": 3, "unitPrice": 20 } }
]
The $lookup operator is used to perform a left outer join between two
collections in MongoDB, allowing you to combine documents from one
collection with documents from another based on a shared field.
Syntax
{
"$lookup": {
"from": "<collection_name>",
"localField": "<field_from_input_documents>",
"foreignField":
"<field_from_documents_of_the_from_collection>",
"as": "<output_array_field>"
}
}
Parameters
1. orders Collection
[
{ "orderId": 1, "productId": "A", "quantity": 2 },
{ "orderId": 2, "productId": "B", "quantity": 3 }
]
2. products Collection
[
{ "productId": "A", "productName": "Widget", "price":
10 },
{ "productId": "B", "productName": "Gadget", "price":
20 }
]
Aggregation Query
javascript
Copy code
db.orders.aggregate([
{
$lookup: {
from: 'products',
localField: 'productId',
foreignField: 'productId',
as: 'productDetails'
}
},
{
$unwind: '$productDetails' // Flatten the array of
product details
},
{
$project: {
orderId: 1,
totalAmount: {
$multiply: ['$quantity', '$productDetails.price']
// Calculate total amount
}
}
}
]);
Result
Explanation
Conclusion
The $bucket operator takes a set of documents and divides them into discrete
groups, called buckets, based on a specified field. Each bucket can represent a
range of values, and you can perform aggregate calculations on the documents
in each bucket.
Syntax
{
$bucket: {
groupBy: <expression>, // The field to group
by (e.g., a number or date).
boundaries: [ <boundary1>, <boundary2>, ... ], // An
array of boundary values that define the ranges for the
buckets.
default: <defaultBucket>, // (Optional) Name of
the bucket for values outside the specified boundaries.
output: { // An object defining
what to return for each bucket.
<outputField1>: { <accumulator1>: <expression1> },
...
}
}
}
Example
Imagine you have a collection called scores that contains students'
exam scores:
[
{ "student": "Alice", "score": 85 },
{ "student": "Bob", "score": 92 },
{ "student": "Charlie", "score": 75 },
{ "student": "David", "score": 65 },
{ "student": "Eve", "score": 89 },
{ "student": "Frank", "score": 55 }
]
Using $bucket
You want to group these scores into ranges (buckets) to see how many
students fall into each score range.
Aggregation Query
javascript
Copy code
db.scores.aggregate([
{
$bucket: {
groupBy: "$score", // Group by
the 'score' field.
boundaries: [0, 60, 75, 85, 100], // Define the
boundaries for the buckets.
default: "Other", // Optional:
Name for scores outside the defined ranges.
output: {
count: { $sum: 1 }, // Count the
number of students in each bucket.
totalScore: { $sum: "$score" } // Sum the
scores in each bucket.
}
}
}
]);
Result
[
{ "range": "[0, 60)", "count": 1, "totalScore":
55 }, // 1 student with a score < 60
{ "range": "[60, 75)", "count": 1, "totalScore":
65 }, // 1 student with a score between 60 and 75
{ "range": "[75, 85)", "count": 2, "totalScore":
164 }, // 2 students with scores between 75 and 85
{ "range": "[85, 100)", "count": 2, "totalScore":
177 } // 2 students with scores between 85 and 100
]
Explanation of the Result
Conclusion
Syntax:
{ $out: "outputCollection" }
Example:
[
{ "_id": 1, "product": "Laptop", "amount": 1200,
"status": "completed" },
{ "_id": 2, "product": "Phone", "amount": 800,
"status": "completed" },
{ "_id": 3, "product": "Tablet", "amount": 400,
"status": "pending" },
{ "_id": 4, "product": "Monitor", "amount": 300,
"status": "completed" },
{ "_id": 5, "product": "Keyboard", "amount": 150,
"status": "completed" }
]
Syntax:
{ $facet: { stage1: [ <pipeline1> ], stage2:
[ <pipeline2> ] } }
Example:
[
{ "_id": 1, "product": "Laptop", "amount": 1200,
"status": "completed" },
{ "_id": 2, "product": "Phone", "amount": 800,
"status": "completed" },
{ "_id": 3, "product": "Tablet", "amount": 400,
"status": "pending" },
{ "_id": 4, "product": "Monitor", "amount": 300,
"status": "completed" },
{ "_id": 5, "product": "Keyboard", "amount": 150,
"status": "completed" }
]
The $fill operator in MongoDB is used to fill in gaps in time series data
during an aggregation operation. Specifically, it allows you to specify default
values for fields when there are missing documents for certain time intervals
in the output of an aggregation pipeline.
Syntax
{
$fill: {
output: {
fieldName1: value1,
fieldName2: value2,
// ... additional fields as needed
}
}
}
Example:
Aggregation Query:
You want to get the average temperature for each day, filling missing
days with a default temperature of 0.
db.temperatureReadings.aggregate([
{
$group: {
_id: { $dateTrunc: { date: "$date", unit:
"day" } },
avgTemperature: { $avg: "$temperature" }
}
},
{
$fill: {
output: { avgTemperature: 0 }
}
}
]);
Result:
0. Pipeline:
A pipeline is a series of stages executed in order to process the data.
Each stage transforms the data and passes it to the next stage.
The output of the last stage is the final result of the pipeline.
1. Stage:
A stage is a single operation applied to the data.
It can involve simple transformations or complex aggregations.
Each stage has a specific purpose and is responsible for a single task.
2. Operator:
An operator is a special symbol used to perform specific operations on
the data.
Operators can be mathematical, logical, or comparison-based.
Conclusion
The aggregation framework in MongoDB is a powerful tool for data processing and
analysis, allowing users to perform complex queries and calculations efficiently.
Understanding the concepts of pipelines, stages, and operators is essential for
leveraging this capability effectively.
This counts all documents in the collection where the status field is "active".
Summary:
Single-purpose aggregation methods are used for tasks like counting, finding distinct
values, or basic group operations. They are ideal when you need quick, simple results,
without the need for the more extensive aggregation framework.
ACID
Example: If two customers try to purchase the last item in stock at the
same time, isolation ensures that only one of them completes the
transaction to avoid double selling.
Transactions in MongoDB
o MongoDB generally follows the BASE principles for its consistency model,
especially in the context of its replication and sharding features, where
eventual consistency is prioritized for availability and scalability.
o However, MongoDB transactions, starting from version 4.0, follow ACID
principles for multi-document operations. This means MongoDB can support
ACID transactions (Atomicity, Consistency, Isolation, Durability) when
needed for complex operations like updates across multiple documents or
collections.
Journaling in MongoDB
In MongoDB, journaling is a feature that helps protect your data. When you make
changes to the database, MongoDB first records these changes in a "journal" before
saving them. This journal acts like a backup, so if MongoDB unexpectedly shuts
down, it can use the journal to recover and keep your data safe.
0. Consistency: All nodes have the same data at the same time. Every read
returns the most recent write.
1. Availability: Every request gets a response, even if the data isn't up to date.
The system is always operational.
2. Partition Tolerance: The system continues to work despite network failures
between nodes.
Key Points:
Conclusion:
The CAP theorem helps developers understand the trade-offs in designing distributed
systems, guiding decisions based on specific needs.
o malayalam
Replica Sets are groups of MongoDB servers that maintain the same dataset. A
replica set has:
o Primary Node: The main server where all write operations happen. It
replicates data to secondary nodes.
o Secondary Nodes: Servers that replicate data from the primary. They can
serve read requests if configured, and if the primary fails, one secondary
becomes the new primary.
o Arbiter: A member that does not hold data but helps with elections to decide
which secondary becomes the primary during failover.
Types of Replication
o 1 . Master-Slave Replication (Old model, now deprecated)
How it works: One server (master) handles all the writes, and other
servers (slaves) copy the data from the master.
Problem: If the master goes down, no one can write to the database.
Current Status: No longer used in recent MongoDB versions.
o
How it works: MongoDB data is split into shards (parts), and each
shard is a replica set.
Features:
Used when you need to store huge amounts of data that can't fit
on a single server.
Each shard can handle reads and writes, and data is
automatically distributed across servers.
Current Status: Used for horizontal scaling when the database grows
too large for one replica set.
o
Summary
Type Description Failover Scalability
One master, one or more slaves (old
Master-Slave Manual Limited
model)
Primary and secondary servers
Replica Sets Automatic Can scale reads
(current model)
Data is split across multiple replica Handles huge
Sharded Clusters Automatic
sets data
Delayed Replica A secondary node has a delay for
Manual No impact
Sets recovery
Indexing
Type of Indexing
0. Single Field Index (Default Index)
db.collection.createIndex({ name: 1 })
2. Compound Index
3. Multikey Index
db.collection.createIndex({ tags: 1 })
4. Text Index
5. Hashed Index
6. Geospatial Index
7. Wildcard Index
db.collection.createIndex({ "$**": 1 })
db.logs.insertOne({
message: "Temporary log",
createdAt: new Date() // Current time
});
db.logs.createIndex(
{ "createdAt": 1 }, // Index on createdAt field
{ expireAfterSeconds: 30 } // Expire after 30 seconds
);
o The trade-off
Example of Trade-offs
What is a B-tree?
A B-tree is a type of tree data structure used to organize and store data
efficiently. It’s commonly used in databases and filesystems.
Key Features:
0. Balanced: All leaf nodes (end points) are at the same level,
which keeps the tree balanced.
1. Multi-way Nodes: Each node can have multiple keys and
children, not just two like a regular binary tree.
2. Sorted Data: Keys within each node are kept in sorted order,
making searches faster.
3. Efficient Operations: B-trees allow for quick searching,
inserting, and deleting of keys.
How It Works:
css
Copy code
[10, 20]
/ | \\
/ | \\
[5] [15] [25, 30]
B-trees are great for efficiently managing large amounts of sorted data,
making them ideal for databases where quick access is essential.
o Covered Query
All the fields in the query are part of an index.
All the fields returned in the query are in the same index
Purpose: The primary benefit of a covered query is performance
improvement. Since MongoDB can retrieve the requested data directly
from the index, it avoids the overhead of fetching documents from the
data store, making the query faster and using less I/O.
Requirements for a Covered Query:
0. The query must only reference fields that are part of an index.
1.All fields in the projection (the fields you want to return) must
also be included in the index.
2. The _id field is implicitly included in every index.
Example
Then for second query of similar type it doesn’t race them again.
o GridFS
Database scaling
o Vertical Scaling (Scaling Up)
What it Means: Increasing the capacity of a single MongoDB server
by adding more resources, like CPU, RAM, or storage.
Benefits: Simple to implement, as you’re only working with one
server.
Limitations: Limited by the maximum hardware capacity of that
single server, and costs can increase with higher specifications.
Usage: Useful for small or medium-sized databases where the
workload can be handled by a single, more powerful server.
o Horizontal Scaling (Scaling Out)
What it Means: Adding more servers to distribute the workload,
especially for large databases or high traffic.
Key Methods in MongoDB:
MongoDB uses these techniques to grow with your data and user base,
keeping the database fast and reliable.
Examples:
Enable Profiler for Slow Queries (queries slower than
100ms):
bb.setProfilingLevel(1, { slowms: 100 });
Enable Profiler for All Operations:
db.setProfilingLevel(2);
View Collected Data:
db.system.profile.find().sort({ ts: -1 });
o Syntax
o db.createColllection("cappedCollection", { capped: true, size:
100 })
Explanation
db.createCollection: This is the method used to create a
collection.
"cappedCollection": This is the name of the new capped
collection you want to create.
{ capped: true, size: 100 }: This option specifies that the
collection should be capped, meaning it has a fixed size. In this
case, the size is set to 100 bytes.
o How to check the collection is capped or not
o // if the collection is capped it will return true else it will
return false
o db.collectionName.isCapped();
Clustered collection
A clustered collection organizes data based on a cluster key, which helps store and
retrieve related data more efficiently.
0. Cluster Key:
Documents are stored in a specific order based on this key. For
example, if you often query data by a user_id, setting user_id as the
cluster key will make those queries faster.
1. Efficient Storage:
Clustered collections use less storage for large datasets because they
are ordered, which helps reduce index size.
2. Optimized Performance:
Retrieving data by the cluster key is faster, which can improve
performance in large databases.
Note: As of now, MongoDB doesn’t natively support clustered collections the same
way as some relational databases do, but MongoDB’s indexing and sharding options
offer similar advantages.
WiredTiger
Advantages of WiredTiger:
o Improved performance and storage efficiency for databases with high read and
write demands.
o Lower disk space usage thanks to compression.
o Enhanced concurrency with document-level locking, making it ideal for
workloads with multiple users or applications.
Write Concern: & Read Concern:
o Write Concern: MongoDB double-checks that data is saved.
o Read Concern: MongoDB makes sure data is recent when you read it.
o Write Concern:
Write concern is about making sure your data is saved safely when you add,
change, or delete something.
So, write concern is just how much you want MongoDB to double-check
that your data is saved.
o Read Concern:
Read concern is about how fresh or updated the data is when you read it.
0. Quick Read: You get the data fast, but it might not be the latest from
all servers.
1. Confirmed Read: You get data only after MongoDB checks with
multiple servers. More accurate, but takes a bit longer.
allowDiskUse
The allowDiskUse option in MongoDB is like asking for permission to use disk
space when an aggregation result takes more than the default memory limit of 100
MB.
Normalization
Watch
In MongoDB, watch allows you to see changes in the database as they happen. It's
like keeping an eye on your data so you know when something is added, updated, or
deleted, and you can react to it right away.
Profiler
Profiler helps you track and analyze the performance of your database by logging
information about operations, like queries and updates. It shows which operations are
slow, so you can identify and fix performance problems.
o How to Use:
0. Enable Profiling:
1. db.setProfilingLevel(1, { slowms: 100 });
o Find Slow Queries: Helps you see which queries are slow.
o Improve Performance: Lets you optimize slow operations for faster
performance.
Oplog
In MongoDB, the Oplog (short for operation log) is a special capped collection that
records all changes made to the data in the database. It is used primarily in replica
sets to synchronize data across different members (nodes) of the replica set.