0% found this document useful (0 votes)
21 views147 pages

MongoDB Query Operators Advanced

The document outlines various MongoDB query and update operators, including comparison, logical, evaluation, and element operators, as well as bitwise and geospatial operators. It details how to use these operators for querying, updating documents, and performing aggregations. Additionally, it explains the purpose of the $comment operator for enhancing query readability and traceability in logs.

Uploaded by

sahithi3105
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
21 views147 pages

MongoDB Query Operators Advanced

The document outlines various MongoDB query and update operators, including comparison, logical, evaluation, and element operators, as well as bitwise and geospatial operators. It details how to use these operators for querying, updating documents, and performing aggregations. Additionally, it explains the purpose of the $comment operator for enhancing query readability and traceability in logs.

Uploaded by

sahithi3105
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

MongoDB Query Operators

There are many query operators that can be used to compare and reference document fields.

Comparison

The following operators can be used in queries to compare values:

 $eq: Values are equal

 $ne: Values are not equal

 $gt: Value is greater than another value

 $gte: Value is greater than or equal to another value

 $lt: Value is less than another value

 $lte: Value is less than or equal to another value

 $in: Value is matched within an array

Logical

The following operators can logically compare multiple queries.

 $and: Returns documents where both queries match

 $or: Returns documents where either query matches

 $nor: Returns documents where both queries fail to match

 $not: Returns documents where the query does not match

Evaluation

The following operators assist in evaluating documents.

 $mod: This operator performs a modulo operation on the value of a field and returns
documents where the remainder matches a specified value.

[Link]({ fieldName: { $mod: [divisor, remainder] } })

The mod operation, or modulo operation, is an arithmetic operation that returns the remainder of a
division. For example, 7 mod 3 equals 1 because when 7 is divided by 3, the quotient is 2 and the
remainder is 1. The modulo operator, often represented by the "%" symbol in programming
languages, calculates this remainder.

How it works:

 Dividend: The number being divided.

 Divisor/Modulus: The number that divides the dividend.

 Remainder: The result of the operation.

Example:

7 mod 3 = 1 because 7 = (2 * 3) + 1
10 mod 5 = 0 because 10 = (2 * 5) + 0

11 mod 5 = 1 because 11 = (2 * 5) + 1

$regex: Allows the use of regular expressions when evaluating field values

This operator supports regular expressions for pattern matching in string fields. It's used to
find documents where a field's value matches a given regular expression pattern.

[Link]({ fieldName: { $regex: /pattern/, $options: 'i' } }) // 'i' for case-insensitive

📌 Query

[Link]({ name: { $regex: /^A/, $options: "i" } })

 $regex: /^A/ → This matches names that start with “A”.

 $options: "i" → The "i" stands for case-insensitive matching.

✅ Effect of "i"

Without "i" → only matches names starting with capital A.


With "i" → matches names starting with A or a.

📌 Example Dataset

{ "name": "Anil" },

{ "name": "arjun" },

{ "name": "Priya" }

🔍 Query Results

Without "i":

[Link]({ name: { $regex: /^A/ } })

✅ Output:

{ "name": "Anil" }

With "i":
[Link]({ name: { $regex: /^A/, $options: "i" } })

✅ Output:

{ "name": "Anil" }

{ "name": "arjun" }

👉 So in short:

 i = case-insensitive

 m = multiline mode

 x = extended (ignore whitespace in pattern)

 s = dotall mode (dot matches newline too)

 $text: Performs a text search

This operator performs a text search on the content of fields that have a text index. It's used
for full-text search capabilities.

[Link]({ $text: { $search: "search terms" } })

 $where: Uses a JavaScript expression to match documents

This operator allows you to use JavaScript expressions or functions to evaluate


documents. While powerful, it can be less efficient than other operators for large datasets.

[Link]({ $where: "[Link] > 5" })

🔹 What is $expr?

 $expr allows you to use aggregation expressions inside the find() query.

 Normally, find() only compares fields to constant values. With $expr, you can compare fields
to fields, use operators like $add, $gt, $eq, $mod, etc.
MongoDB Update Operators

There are many update operators that can be used during document updates.

Fields

The following operators can be used to update fields:

 $currentDate: Sets the field value to the current date

 $inc: Increments the field value

 $rename: Renames the field

 $set: Sets the value of a field

 $unset: Removes the field from the document

Array

The following operators assist with updating arrays.

 $addToSet: Adds elements to an array only if they do not already exist in the array.

 $pop: Removes the first or last element from an array.

 $pull: Removes all instances of a specified value or elements matching a query from an array.

 $pullAll: Removes all instances of the specified values from an array.

 $push: Adds elements to an array. This can be combined with modifiers like $each, $position,
$slice, and $sort for more controlled array manipulation.

 Positional Operators ($, $[], $[<identifier>]):

1. $: Updates the first element that matches the query condition in an array.
2. $[]: Updates all elements in an array.
3. $[<identifier>]: Updates elements in an array that match a specific filter condition.

Array Aggregation Expression Operators:

 $arrayElemAt: Returns the element at a specified index in an array.

 $concatArrays: Concatenates arrays to return a new array.

 $filter: Selects a subset of an array based on a specified condition.

 $isArray: Returns true if the operand is an array, false otherwise.

 $map: Applies a sub-expression to each element of an array and returns a new array with the
results.

 $range: Generates an array containing a sequence of numbers.

 $reverseArray: Returns an array with the elements in reverse order.

 $slice: Returns a subset of an array.

 $sortArray: Sorts the elements of an array.


 $zip: Combines multiple arrays into an array of arrays.

Element Operators mongodb

MongoDB element operators allow querying documents based on the existence and type of fields
within those documents. The two primary element operators are $exists and $type.

1. $exists Operator:

The $exists operator checks for the presence or absence of a specified field in a document.

• Syntax: { field: { $exists: &lt;boolean&gt; } }

• Behavior:

• If &lt;boolean&gt; is true, the query returns documents where the field exists.

• If &lt;boolean&gt; is false, the query returns documents where the field does not exist.

Example:

To find all products that have a discount field:

[Link]({ discount: { $exists: true } });

To find all products that do not have a discount field:

[Link]({ discount: { $exists: false } });

2. $type Operator:

The $type operator selects documents where the value of a field is of a specified BSON type.

• Syntax: { field: { $type: &lt;BSON type number or string alias&gt; } }

• Behavior: The query returns documents where the field holds a value of the specified BSON type.
You can use either the numeric code or the string alias for the BSON type.

Example:

To find all users where the age field is an integer:

[Link]({ age: { $type: "int" } });

// or using the numeric code

[Link]({ age: { $type: 16 } });


To find all products where the price field is a double:

[Link]({ price: { $type: "double" } });

----------------------------------------------------------------------------------------------------------------------

Bitwise Operators:

MongoDB offers several bitwise operators for querying and updating documents based on the
individual bits within numeric or binary values. These operators are useful for scenarios like
managing permissions, tracking feature flags, or efficiently storing boolean states.

Bitwise Query Predicate Operators:

These operators are used in query conditions to match documents where specific bit patterns are
found in a field.

 $bitsAllClear: Matches documents where all specified bit positions in a field have a value of 0
(are clear).

[Link]({ field: { $bitsAllClear: <bitmask or array of bit positions> } });

 $bitsAllSet: Matches documents where all specified bit positions in a field have a value of 1
(are set).

[Link]({ field: { $bitsAllSet: <bitmask or array of bit positions> } });

 $bitsAnyClear: Matches documents where at least one of the specified bit positions in a field
has a value of 0 (is clear).

[Link]({ field: { $bitsAnyClear: <bitmask or array of bit positions> } });

 $bitsAnySet: Matches documents where at least one of the specified bit positions in a field
has a value of 1 (is set).

[Link]({ field: { $bitsAnySet: <bitmask or array of bit positions> } });

Bitwise Update Operator:


This operator is used in update operations to modify the bits of an integer field.

 $bit: Performs a bitwise update (AND, OR, or XOR) on an integer field.

[Link](
{ <query> },
{ $bit: { <field>: { <and|or|xor>: <integer_value> } } }
);

Aggregation Bitwise Operators:

MongoDB's aggregation framework also includes operators for bitwise operations within pipelines.

 $bitAnd: Performs a bitwise AND operation on two or more expressions.

 $bitOr: Performs a bitwise OR operation on two or more expressions.

 $bitXor: Performs a bitwise XOR operation on two or more expressions.

 $bitNot: Performs a bitwise NOT operation on an expression.

These aggregation operators are typically used within $project or $addFields stages to create new
fields or modify existing ones based on bitwise logic.
Geospatial Operator in MongoDB offers robust capabilities for handling and querying geospatial
data, enabling applications to perform location-based searches and analysis.

1. Storing Geospatial Data:

 GeoJSON: The preferred format for storing geospatial data in MongoDB. It represents
geographical features like points, lines, and polygons using a JSON structure.

{
"location": {
"type": "Point",
"coordinates": [-73.97, 40.77] // [longitude, latitude]
},
"name": "Central Park"
}

 Legacy Coordinate Pairs: MongoDB also supports storing coordinates as simple arrays
[longitude, latitude], which are interpreted on a Euclidean plane. However, GeoJSON is
recommended for its richer features and spherical interpretations.

2. Geospatial Indexes:

 2dsphere Index: Essential for efficient geospatial queries, especially those interpreting
geometry on a sphere (like Earth). It's created on the field containing the GeoJSON object.

[Link]({ "location": "2dsphere" })

 2d Index: Supports queries on a flat surface and some spherical queries, but 2dsphere is
generally preferred for spherical operations to avoid potential errors.

3. Geospatial Queries:

MongoDB provides various query operators and commands for geospatial operations:

 $near and $nearSphere: Find documents near a specified point. $nearSphere explicitly
performs spherical queries and is recommended when working with GeoJSON and a
2dsphere index.

[Link]({
"location": {
"$nearSphere": {
"$geometry": {
"type": "Point",
"coordinates": [-73.96, 40.78]
},
"$maxDistance": 1000 // meters
}
}
})

 $geoWithin: Find documents whose geospatial data is entirely contained within a specified
shape (e.g., a polygon or a circle).

[Link]({
"location": {
"$geoWithin": {
"$geometry": {
"type": "Polygon",
"coordinates": [
[
[-74.01, 40.70], [-73.99, 40.75], [-73.95, 40.73], [-74.01, 40.70]
]
]
}
}
}
})

 $geoIntersects: Find documents whose geospatial data intersects with a specified shape.

 $box, $center, $centerSphere, $polygon: Legacy operators for defining shapes in 2d indexes,
often used with $geoWithin.

4. Aggregation Pipeline Stages:

 $geoNear: An aggregation stage that performs a geospatial query and returns documents
sorted by distance from a specified point. It can also calculate the distance and include it in
the output.

These features enable developers to build powerful location-aware applications, from finding nearby
points of interest to analyzing spatial relationships between data.
MongoDB offers the $comment meta-operator to attach comments to queries, making them easier
to understand and trace in logs. This operator is particularly useful for database administrators and
developers who need to analyze MongoDB's profile logs.

Purpose of $comment:

 Improved Readability: Comments clarify the intent and logic behind complex queries,
especially when reviewing code or revisiting older queries.

 Enhanced Traceability: The $comment operator ensures that the attached comment
propagates to the MongoDB profile log, allowing for easier identification and interpretation
of query performance and execution details.

Usage:

The $comment operator can be included within query predicates or aggregation pipeline stages.

Example in a find() query:

[Link]({
"field": "value",
"$comment": "Retrieving documents where 'field' equals 'value' for analysis"
});

Example in an aggregation pipeline:

[Link]([
{
$match: {
"status": "active",
"$comment": "Filtering active users"
}
},
{
$group: {
_id: "$category",
count: { $sum: 1 }
}
}
]);
Note: The $comment operator is a meta-operator and does not affect the query's execution or the
returned results. Its sole purpose is to provide descriptive information within the query and the
profile logs.

Aggregation Pipelines

Aggregation operations allow you to group, sort, perform calculations, analyze data, and much more.

Aggregation pipelines can have one or more "stages". The order of these stages are important. Each
stage acts upon the results of the previous stage.

[Link]([

// Stage 1: Only find documents that have more than 1 like

$match: { likes: { $gt: 1 } }

},

// Stage 2: Group documents by category and sum each categories likes

$group: { _id: "$category", totalLikes: { $sum: "$likes" } }

Aggregation $group

This aggregation stage groups documents by the unique _id expression provided.

Aggregation $limit

This aggregation stage limits the number of documents passed to the next stage.
Aggregation $project

This aggregation stage passes only the specified fields along to the next aggregation stage.

[Link]([

$project: {

"name": 1,

"cuisine": 1,

"address": 1

},

$limit: 5

])

Aggregation $sort

This aggregation stage groups sorts all documents in the specified sort order.

[Link]([

$sort: { "accommodates": -1 }

},

$project: {

"name": 1,

"accommodates": 1

},

$limit: 5

}
])

Aggregation $match

This aggregation stage behaves like a find. It will filter documents that match the query provided.

[Link]([

{ $match : { property_type : "House" } },

{ $limit: 2 },

{ $project: {

"name": 1,

"bedrooms": 1,

"price": 1

}}

])

Aggregation $addFields

This aggregation stage adds new fields to documents.

[Link]([

$addFields: {

avgGrade: { $avg: "$[Link]" }

},

$project: {

"name": 1,

"avgGrade": 1

},

$limit: 5

])
Aggregation $count

This aggregation stage counts the total amount of documents passed from the previous stage.

[Link]([

$match: { "cuisine": "Chinese" }

},

$count: "totalChinese"

])

This will return the number of documents at the $count stage as a field called "totalChinese".

Aggregation $lookup

This aggregation stage performs a left outer join to a collection in the same database.

There are four required fields:

 from: The collection to use for lookup in the same database

 local Field: The field in the primary collection that can be used as a unique identifier in
the from collection.

 foreign Field: The field in the from collection that can be used as a unique identifier in the
primary collection.

 as: The name of the new field that will contain the matching documents from
the from collection.

[Link]([

$lookup: {

from: "movies",

localField: "movie_id",

foreignField: "_id",

as: "movie_details",

},

},

$limit: 1
}

])

Aggregation $out

This aggregation stage writes the returned documents from the aggregation pipeline to a collection.

[Link]([

$group: {

_id: "$property_type",

properties: {

$push: {

name: "$name",

accommodates: "$accommodates",

price: "$price",

},

},

},

},

{ $out: "properties_by_type" },

])

The first stage will group properties by the property_type and include the name, accommodates,
and price fields for each. The $out stage will create a new collection called properties_by_type in the
current database and write the resulting documents into that collection.

Indexing & Search

MongoDB Atlas comes with a full-text search engine that can be used to search for documents in a
collection.

Indexing in MongoDB is a crucial feature that enhances query processing efficiency. Without
indexing, MongoDB must scan every document in a collection to retrieve the matching documents
and leading to slower query performance.
Indexes are special data structures that store information about the documents in a way that makes
it easier for MongoDB to quickly locate the right data.

-------------------------------------------------------------------------------------------------------------------------------------

MongoDB – Employee Database

Dataset

[Link]([

emp_id: 201,

name: "Arjun",

skills: ["Java", "SQL", "Python"],

salary: 50000,

experience: [2, 3, 4]

},

emp_id: 202,

name: "Meera",

skills: ["HTML", "CSS", "JavaScript"],

salary: 45000,

experience: [1, 2, 2]

])

a. Show emp_id and name where average experience > 2 years

[Link]([

{ $project: { emp_id: 1, name: 1, avg_exp: { $avg: "$experience" } } },

{ $match: { avg_exp: { $gt: 2 } } }

])

b. Find average salary of all employees

[Link]([

{ $group: { _id: null, avg_salary: { $avg: "$salary" } } }

])
c. Display the second skill of Arjun

[Link](

{ name: "Arjun" },

{ "skills.1": 1, _id: 0 }

d. Find difference between maximum and minimum experience of Meera

[Link]([

{ $match: { name: "Meera" } },

{ $project: {

diff: { $subtract: [ { $max: "$experience" }, { $min: "$experience" } ] }

}}

])

MongoDB – Updates & Aggregations (Employee DB)

a. Increase salary of all employees by 10%

[Link](

{},

[{ $set: { salary: { $multiply: ["$salary", 1.10] } } }]

b. Update each employee with total_experience (sum of array)

[Link](

{},

[{ $set: { total_experience: { $sum: "$experience" } } }]

c. Find employee with highest average experience

[Link]([

{ $project: { name: 1, avg_exp: { $avg: "$experience" } } },

{ $sort: { avg_exp: -1 } },

{ $limit: 1 }

])

d. Show employees sorted by salary (descending)


[Link]({}, { name: 1, salary: 1, _id: 0 }).sort({ salary: -1 })

e. Add status field = "active" to all

[Link]({}, { $set: { status: "active" } })

MongoDB – Advanced Queries (Employee DB)

a. Show employees where any experience < 2 years

[Link]({ experience: { $elemMatch: { $lt: 2 } } })

b. Add grade field = "Senior" if avg experience ≥ 3 else "Junior"

[Link](

{},

[{ $set: { grade: { $cond: [ { $gte: [ { $avg: "$experience" }, 3 ] }, "Senior", "Junior" ] } } }]

c. Remove skills field for employees with salary < 48000

[Link](

{ salary: { $lt: 48000 } },

{ $unset: { skills: "" } }

d. Show employees where skills array does not contain exactly 3 elements

[Link]({ $expr: { $ne: [ { $size: "$skills" }, 3 ] } })

e. Create unique index on emp_id

[Link]({ emp_id: 1 }, { unique: true })


Employee Database

a. Employees with avg experience > 2

[ { "emp_id": 201, "name": "Arjun", "avg_experience": 3.0 } ]

b. Average salary

{ "avg_salary": 47500.0 }

c. Second skill of Arjun

{ "Arjun_second_skill": "SQL" }

d. Difference between max & min experience of Meera

{ "Meera_experience_diff": 1 }

Updates & Aggregations

a. Salary after 10% increment

[ { "name": "Arjun", "new_salary": 55000.0 },

{ "name": "Meera", "new_salary": 49500.0 } ]

b. Total experience of each employee

[ { "name": "Arjun", "total_experience": 9 },

{ "name": "Meera", "total_experience": 5 } ]

c. Employee with highest avg experience

{ "highest_avg_experience": "Arjun", "avg_exp": 3.0 }

d. Sorted by salary (descending)

[ { "name": "Arjun", "salary": 55000.0 },

{ "name": "Meera", "salary": 49500.0 } ]

e. Status field added

[ { "name": "Arjun", "status": "active" },

{ "name": "Meera", "status": "active" } ]

Advanced Queries outputs

a. Employees with any experience < 2

["Meera"]
b. Grade assignment

[ { "name": "Arjun", "grade": "Senior" },

{ "name": "Meera", "grade": "Junior" } ]

c. After removing skills where salary < 48000


(No one removed here since both salaries are ≥ 48000)

"emp_id": 201, "name": "Arjun", "skills": ["Java","SQL","Python"],

"salary": 55000.0, "experience": [2,3,4],

"total_experience": 9, "avg_experience": 3.0,

"status": "active", "grade": "Senior"

},

"emp_id": 202, "name": "Meera", "skills": ["HTML","CSS","JavaScript"],

"salary": 49500.0, "experience": [1,2,2],

"total_experience": 5, "avg_experience": 1.67,

"status": "active", "grade": "Junior"

d. Employees with skills array length ≠ 3

[]

e. Unique index creation

"Unique index created on emp_id"


(MongoDB Query and Projection Operators).

Here’s a working example:

Sample Collection: employees

[Link]([

{ "name": "Alice", "age": 25, "department": "HR", "skills": ["Excel", "Recruitment"], "salary":
35000 },

{ "name": "Bob", "age": 30, "department": "IT", "skills": ["Java", "MongoDB", "[Link]"], "salary":
60000 },

{ "name": "Charlie", "age": 28, "department": "Finance", "skills": ["Accounting", "Excel"], "salary":
45000 },

{ "name": "David", "age": 35, "department": "IT", "skills": ["Python", "AWS"], "salary": 75000 },

{ "name": "Eva", "age": 22, "department": "HR", "skills": ["Communication", "Excel"], "salary":
30000 }

])

Example 1: Comparison Operator ($gte)

Find employees with salary greater than or equal to 50,000.

[Link]({ "salary": { $gte: 50000 } }, { _id: 0, name: 1, salary: 1 })

✅ Output:

{ "name": "Bob", "salary": 60000 }

{ "name": "David", "salary": 75000 }

Example 2: Logical Operator ($or)

Find employees who are in IT department OR have age less than 25.

[Link](

{ $or: [ { "department": "IT" }, { "age": { $lt: 25 } } ] },

{ _id: 0, name: 1, age: 1, department: 1 }

✅ Output:
{ "name": "Alice", "age": 25, "department": "HR" }

{ "name": "Bob", "age": 30, "department": "IT" }

{ "name": "David", "age": 35, "department": "IT" }

{ "name": "Eva", "age": 22, "department": "HR" }

Example 3: Array Operator ($elemMatch)

Find employees who have "Excel" in their skills.

[Link](

{ "skills": { $elemMatch: { $eq: "Excel" } } },

{ _id: 0, name: 1, skills: 1 }

✅ Output:

{ "name": "Alice", "skills": ["Excel", "Recruitment"] }

{ "name": "Charlie", "skills": ["Accounting", "Excel"] }

{ "name": "Eva", "skills": ["Communication", "Excel"] }


📂 Sample Collection: employees

[Link]([

{ "name": "Alice", "age": 25, "department": "HR", "skills": ["Excel", "Recruitment"], "salary": 35000,
"likes": 3 },

{ "name": "Bob", "age": 30, "department": "IT", "skills": ["Java", "MongoDB", "[Link]"], "salary":
60000, "likes": 5 },

{ "name": "Charlie", "age": 28, "department": "Finance", "skills": ["Accounting", "Excel"], "salary":
45000, "likes": 2 },

{ "name": "David", "age": 35, "department": "IT", "skills": ["Python", "AWS"], "salary": 75000,
"likes": 4 },

{ "name": "Eva", "age": 22, "department": "HR", "skills": ["Communication", "Excel"], "salary":
30000, "likes": 1 }

])

🔹 1. Comparison Operators

(a) $gte – Salary greater than or equal to 50,000

[Link]({ "salary": { $gte: 50000 } }, { _id: 0, name: 1, salary: 1 })

✅ Output:

{ "name": "Bob", "salary": 60000 }

{ "name": "David", "salary": 75000 }

(b) $eq – Find employee named "Alice"

[Link]({ "name": { $eq: "Alice" } }, { _id: 0, name: 1, department: 1 })

✅ Output:

{ "name": "Alice", "department": "HR" }

🔹 2. Logical Operators

(a) $and – Employees in IT department AND salary > 60,000

[Link](

{ $and: [ { "department": "IT" }, { "salary": { $gt: 60000 } } ] },

{ _id: 0, name: 1, department: 1, salary: 1 }


)

✅ Output:

{ "name": "David", "department": "IT", "salary": 75000 }

(b) $or – Employees in HR OR age < 25

[Link](

{ $or: [ { "department": "HR" }, { "age": { $lt: 25 } } ] },

{ _id: 0, name: 1, age: 1, department: 1 }

✅ Output:

{ "name": "Alice", "age": 25, "department": "HR" }

{ "name": "Eva", "age": 22, "department": "HR" }

Employee Database example with Logical Operators: $not and $nor.

[Link]([

{ "name": "Alice", "age": 25, "department": "HR", "salary": 35000 },

{ "name": "Bob", "age": 30, "department": "IT", "salary": 60000 },

{ "name": "Charlie", "age": 28, "department": "Finance", "salary": 45000 },

{ "name": "David", "age": 35, "department": "IT", "salary": 75000 },

{ "name": "Eva", "age": 22, "department": "HR", "salary": 30000 }

])

$not Operator

👉 $not inverts the result of another condition.


Example: Find employees whose salary is NOT greater than 50,000.

[Link](

{ "salary": { $not: { $gt: 50000 } } },

{ _id: 0, name: 1, salary: 1 }

✅ Output:

{ "name": "Alice", "salary": 35000 }

{ "name": "Charlie", "salary": 45000 }


{ "name": "Eva", "salary": 30000 }

$nor Operator

👉 $nor means none of the conditions should be true.


Example: Find employees who are NOT in IT department NOR have salary above 50,000.

[Link](

{ $nor: [ { "department": "IT" }, { "salary": { $gt: 50000 } } ] },

{ _id: 0, name: 1, department: 1, salary: 1 }

✅ Output:

{ "name": "Alice", "department": "HR", "salary": 35000 }

{ "name": "Charlie", "department": "Finance", "salary": 45000 }

{ "name": "Eva", "department": "HR", "salary": 30000 }

📌 Summary

 $not → Negates a single condition.

 $nor → Negates multiple conditions (returns docs that don’t satisfy any of them).

🔹 3. Array Operators

(a) $all – Employees who know Excel AND Recruitment

[Link](

{ "skills": { $all: ["Excel", "Recruitment"] } },

{ _id: 0, name: 1, skills: 1 }

✅ Output:

{ "name": "Alice", "skills": ["Excel", "Recruitment"] }

(b) $elemMatch – Employees who have Excel as one of the skills

[Link](

{ "skills": { $elemMatch: { $eq: "Excel" } } },

{ _id: 0, name: 1, skills: 1 }


)

✅ Output:

{ "name": "Alice", "skills": ["Excel", "Recruitment"] }

{ "name": "Charlie", "skills": ["Accounting", "Excel"] }

{ "name": "Eva", "skills": ["Communication", "Excel"] }

🔹 4. Evaluation Operators

(a) $mod – Employees whose salary divisible by 10,000

[Link](

{ "salary": { $mod: [10000, 0] } },

{ _id: 0, name: 1, salary: 1 }

✅ Output:

{ "name": "Bob", "salary": 60000 }

(b) $expr – Employees where salary > (age * 2000)

[Link](

{ $expr: { $gt: ["$salary", { $multiply: ["$age", 2000] }] } },

{ _id: 0, name: 1, salary: 1, age: 1 }

✅ Output:

{ "name": "Bob", "age": 30, "salary": 60000 }

{ "name": "David", "age": 35, "salary": 75000 }

Example 1 – Compare Two Fields

Suppose you have a collection employees:

{ "name": "Alice", "salary": 5000, "bonus": 2000 },

{ "name": "Bob", "salary": 7000, "bonus": 1000 },

{ "name": "Charlie", "salary": 4000, "bonus": 1500 }

✅ Find employees where bonus > salary:


[Link]({

$expr: { $gt: ["$bonus", "$salary"] }

})

Output:

(no result here, since no bonus > salary)

Example 2 – Field vs Computed Expression

Find employees where salary > bonus * 3:

[Link]({

$expr: { $gt: ["$salary", { $multiply: ["$bonus", 3] }] }

})

Output:

{ "name":"Bob", "salary":7000, "bonus":1000 }

{ "name":"Charlie", "salary":4000, "bonus":1500 }

Example 3 – Using $mod

Dataset:

{ "roll": 201, "name": "Arjun", "totalMarks": 253 },

{ "roll": 202, "name": "Meera", "totalMarks": 285 }

✅ Find students whose totalMarks divisible by 2:

[Link]({

$expr: { $eq: [ { $mod: ["$totalMarks", 2] }, 0 ] }

})

Output:

{ "roll":202, "name":"Meera", "totalMarks":285 } ❌ (not divisible)

{ "roll":201, "name":"Arjun", "totalMarks":253 } ❌ (not divisible)

👉 If one student had totalMarks = 220, it would appear in output.

Example 4 – Dynamic Filtering


Find employees whose salary + bonus > 6000:

[Link]({

$expr: { $gt: [ { $add: ["$salary", "$bonus"] }, 6000 ] }

})

Output:

{ "name":"Alice","salary":5000,"bonus":2000 }

{ "name":"Bob","salary":7000,"bonus":1000 }

👉 In short:

 $expr lets you use aggregation expressions inside queries.

 Very useful when you need field-to-field comparisons or calculations in find().

🔹 5. Element Operators

(a) $exists – Employees having likes field

[Link]({ "likes": { $exists: true } }, { _id: 0, name: 1, likes: 1 })

(b) $type – Employees where age is an integer

[Link]({ "age": { $type: 16 } }, { _id: 0, name: 1, age: 1 })

🔹 6. Projection Operators(What if you don’t mention _id?- By default, MongoDB always includes
_id unless you explicitly set _id: 0)

(a) Include only name and department

[Link]({}, { _id: 0, name: 1, department: 1 })

(b) Exclude salary field

[Link]({}, { salary: 0 })

📂 Updated Sample Collection: employees


[Link]([

{ "name": "Alice", "age": 25, "department": "HR", "skills": ["Excel", "Recruitment"], "salary": 35000,
"likes": 3, "permissions": 5, "location": { "type": "Point", "coordinates": [77.5946, 12.9716] } }, //
Bangalore

{ "name": "Bob", "age": 30, "department": "IT", "skills": ["Java", "MongoDB", "[Link]"], "salary":
60000, "likes": 5, "permissions": 6, "location": { "type": "Point", "coordinates": [72.8777, 19.0760] } },
// Mumbai

{ "name": "Charlie", "age": 28, "department": "Finance", "skills": ["Accounting", "Excel"], "salary":
45000, "likes": 2, "permissions": 3, "location": { "type": "Point", "coordinates": [80.2785, 13.0827] } },
// Chennai

{ "name": "David", "age": 35, "department": "IT", "skills": ["Python", "AWS"], "salary": 75000,
"likes": 4, "permissions": 7, "location": { "type": "Point", "coordinates": [88.3639, 22.5726] } }, //
Kolkata

{ "name": "Eva", "age": 22, "department": "HR", "skills": ["Communication", "Excel"], "salary":
30000, "likes": 1, "permissions": 4, "location": { "type": "Point", "coordinates": [77.2090, 28.6139] } }
// Delhi

])

⚠️Before using geospatial queries, create a 2dsphere index:

[Link]({ location: "2dsphere" })

🔹 7. Geospatial Operators

(a) $near – Employees near Delhi (77.2090, 28.6139) within ~500 km

[Link]({

location: {

$near: {

$geometry: { type: "Point", coordinates: [77.2090, 28.6139] },

$maxDistance: 500000 // in meters (~500 km)

}, { _id: 0, name: 1, location: 1 })

✅ Example Output:

{ "name": "Eva", "location": { "type": "Point", "coordinates": [77.209, 28.6139] } }

{ "name": "Alice", "location": { "type": "Point", "coordinates": [77.5946, 12.9716] } }


(b) $geoWithin – Employees inside a circle around Mumbai (within 300 km)

[Link]({

location: {

$geoWithin: {

$centerSphere: [ [72.8777, 19.0760], 300/6378.1 ]

// radius in radians = distance(km)/earth_radius

}, { _id: 0, name: 1, location: 1 })

✅ Example Output:

{ "name": "Bob", "location": { "type": "Point", "coordinates": [72.8777, 19.076] } }

🔹 8. Bitwise Operators

Assume permissions is a bitmask field:

 Bit 0 → Read Access

 Bit 1 → Write Access

 Bit 2 → Admin Access

So for example:

 5 (binary 101) → Read + Admin

 6 (binary 110) → Write + Admin

 7 (binary 111) → Read + Write + Admin

(a) $bitsAllSet – Employees with Read + Admin access

[Link](

{ "permissions": { $bitsAllSet: 5 } }, // 101 → check bits 0 & 2

{ _id: 0, name: 1, permissions: 1 }

✅ Output:

{ "name": "Alice", "permissions": 5 }

{ "name": "David", "permissions": 7 }


(b) $bitsAnySet – Employees with either Read OR Write access

[Link](

{ "permissions": { $bitsAnySet: 3 } }, // 011 → check bits 0 or 1

{ _id: 0, name: 1, permissions: 1 }

✅ Output:

{ "name": "Alice", "permissions": 5 }

{ "name": "Bob", "permissions": 6 }

{ "name": "Charlie", "permissions": 3 }

{ "name": "David", "permissions": 7 }

(c) $bitsAllClear – Employees with no Write access (bit 1 = 0)

[Link](

{ "permissions": { $bitsAllClear: 2 } }, // 010 → check if bit 1 is 0

{ _id: 0, name: 1, permissions: 1 }

✅ Output:

{ "name": "Alice", "permissions": 5 }

{ "name": "Eva", "permissions": 4 }

MongoDB provides bitwise query operators that allow you to filter documents based on bitwise
operations on numeric fields (commonly used with integers that represent flags, permissions, or
status codes).

Common Bitwise Operators in MongoDB

 $bitsAllSet → Matches if all specified bits are 1.

 $bitsAnySet → Matches if any specified bits are 1.

 $bitsAllClear → Matches if all specified bits are 0.

 $bitsAnyClear → Matches if any specified bits are 0.


Example Employee Dataset

Let’s assume we store employee access permissions in a single integer field called accessFlags.

Each bit represents a permission:

 1 → View Reports

 2 → Edit Reports

 4 → Approve Leave

 8 → Manage Payroll

So, if an employee has accessFlags = 13, binary is 1101, meaning:

 View Reports ✅

 Edit Reports ❌

 Approve Leave ✅

 Manage Payroll ✅

Sample Documents

{ "_id": 1, "name": "Alice", "accessFlags": 1 }, // 0001 -> View Reports

{ "_id": 2, "name": "Bob", "accessFlags": 3 }, // 0011 -> View + Edit

{ "_id": 3, "name": "Charlie", "accessFlags": 5 }, // 0101 -> View + Approve Leave

{ "_id": 4, "name": "David", "accessFlags": 13 }, // 1101 -> View + Approve Leave + Manage Payroll

{ "_id": 5, "name": "Eve", "accessFlags": 8 } // 1000 -> Manage Payroll

Queries with Bitwise Operators

1. Find employees who have Approve Leave permission (bit 2 = 4)

[Link]({

accessFlags: { $bitsAllSet: [5] }

})

✅ Output:

{ "_id": 3, "name": "Charlie", "accessFlags": 5 },

{ "_id": 4, "name": "David", "accessFlags": 13 }


]

2. Find employees who can either Edit Reports OR Manage Payroll (bit 1 or bit 3)

[Link]({

accessFlags: { $bitsAnySet: [1, 3] }

})

✅ Output:

{ "_id": 2, "name": "Bob", "accessFlags": 3 },

{ "_id": 4, "name": "David", "accessFlags": 13 },

{ "_id": 5, "name": "Eve", "accessFlags": 8 }

3. Find employees who have no Manage Payroll rights (bit 3 must be 0)

[Link]({

accessFlags: { $bitsAllClear: [3] }

})

✅ Output:

{ "_id": 1, "name": "Alice", "accessFlags": 1 },

{ "_id": 2, "name": "Bob", "accessFlags": 3 },

{ "_id": 3, "name": "Charlie", "accessFlags": 5 }

4. Find employees missing at least one of (View + Edit Reports)

(bits 0 and 1 → at least one must be 0)

[Link]({

accessFlags: { $bitsAnyClear: [0, 1] }

})

✅ Output:

[
{ "_id": 1, "name": "Alice", "accessFlags": 1 },

{ "_id": 3, "name": "Charlie", "accessFlags": 5 },

{ "_id": 4, "name": "David", "accessFlags": 13 },

{ "_id": 5, "name": "Eve", "accessFlags": 8 }

👉 This way, bitwise operations make it easy to handle permissions, roles, and flags efficiently in
MongoDB.
Employee Database Evaluation Operators: $regex, $text, and $where.

[Link]([

{ "name": "Alice", "age": 25, "department": "HR", "salary": 35000 },

{ "name": "Bob", "age": 30, "department": "IT", "salary": 60000 },

{ "name": "Charlie", "age": 28, "department": "Finance", "salary": 45000 },

{ "name": "David", "age": 35, "department": "IT", "salary": 75000 },

{ "name": "Eva", "age": 22, "department": "HR", "salary": 30000 }

])

🔹 1. $regex (Pattern Matching)

👉 Find employees whose names start with "A".

[Link](

{ "name": { $regex: /^A/, $options: "i" } }, // ^A = starts with A, i = case insensitive

{ _id: 0, name: 1 }

✅ Output:

{ "name": "Alice" }

🔹 2. $text (Full-Text Search)

👉 First, create a text index on department field:

[Link]({ department: "text" })

👉 Query employees whose department text contains "IT":


[Link](

{ $text: { $search: "IT" } },

{ _id: 0, name: 1, department: 1 }

✅ Output:

{ "name": "Bob", "department": "IT" }

{ "name": "David", "department": "IT" }

🔹 3. $where (JavaScript Condition)

👉 Find employees where age is greater than salary / 2000:

[Link](

{ $where: "[Link] > ([Link] / 2000)" },

{ _id: 0, name: 1, age: 1, salary: 1 }

✅ Output (example):

{ "name": "Alice", "age": 25, "salary": 35000 }

{ "name": "Eva", "age": 22, "salary": 30000 }

🔹 $expr (Expression Evaluation)

👉 $expr allows us to use aggregation expressions inside queries.


It is faster and safer than $where because it doesn’t use raw JavaScript.

Example 1: Salary greater than age × 2000

[Link](

{ $expr: { $gt: ["$salary", { $multiply: ["$age", 2000] }] } },

{ _id: 0, name: 1, age: 1, salary: 1 }

✅ Output:

{ "name": "Bob", "age": 30, "salary": 60000 }


{ "name": "David", "age": 35, "salary": 75000 }

Example 2: Employees where age < salary / 3000

[Link](

{ $expr: { $lt: ["$age", { $divide: ["$salary", 3000] }] } },

{ _id: 0, name: 1, age: 1, salary: 1 }

✅ Output:

{ "name": "Alice", "age": 25, "salary": 35000 }

{ "name": "Charlie", "age": 28, "salary": 45000 }

{ "name": "Eva", "age": 22, "salary": 30000 }

📌 Summary of Evaluation Operators (Employee DB)

1. $regex → Pattern match (e.g., names starting with A).

2. $text → Full-text search (requires text index).

3. $where → Custom JavaScript condition (slower, less safe).

4. $expr → Expression-based conditions (fast, preferred over $where).


📌 1. Redis List as a Stack (LIFO – Last In, First Out)

👉 Use LPUSH to insert items (push to the left)


👉 Use LPOP to remove items (pop from the left)

Example:

LPUSH stack 10 # stack = [10]

LPUSH stack 20 # stack = [20, 10]

LPUSH stack 30 # stack = [30, 20, 10]

LPOP stack # Removes 30 (Last pushed)

LPOP stack # Removes 20

LPOP stack # Removes 10

✅ Order of removal: 30 → 20 → 10

📌 2. Redis List as a Queue (FIFO – First In, First Out)

👉 Use RPUSH to insert items (push to the right)


👉 Use LPOP to remove items (pop from the left)

Example:

RPUSH queue A # queue = [A]

RPUSH queue B # queue = [A, B]

RPUSH queue C # queue = [A, B, C]

LPOP queue # Removes A (First inserted)

LPOP queue # Removes B

LPOP queue # Removes C


✅ Order of removal: A → B → C

📌 Summary

 Stack (LIFO) → LPUSH + LPOP

 Queue (FIFO) → RPUSH + LPOP

📚 Case Study: Library Book Borrow & Return System

We will manage a list of borrowed books in Redis.

🔹 1. Using Redis List as a Stack (LIFO – Last In, First Out)

👉 Example Use Case:


When books are scanned for return, the last returned book is processed first.

Redis Commands:

LPUSH returned_books "Book_A"

LPUSH returned_books "Book_B"

LPUSH returned_books "Book_C"

Now the list is:

["Book_C", "Book_B", "Book_A"]

Process return:

LPOP returned_books # → "Book_C"

LPOP returned_books # → "Book_B"

LPOP returned_books # → "Book_A"

✅ Order of processing: Book_C → Book_B → Book_A

🔹 2. Using Redis List as a Queue (FIFO – First In, First Out)

👉 Example Use Case:


When students borrow books, the first borrower in line should get served first.

Redis Commands:

RPUSH borrowed_books "Student1_BookX"

RPUSH borrowed_books "Student2_BookY"

RPUSH borrowed_books "Student3_BookZ"

Now the list is:


["Student1_BookX", "Student2_BookY", "Student3_BookZ"]

Process borrow:

LPOP borrowed_books # → "Student1_BookX"

LPOP borrowed_books # → "Student2_BookY"

LPOP borrowed_books # → "Student3_BookZ"

✅ Order of service: Student1 → Student2 → Student3

📌 Summary (Library System)

 Stack (LIFO):
Used for book returns → last returned is processed first.
(LPUSH + LPOP)

 Queue (FIFO):
Used for book borrowing queue → first borrower is served first.
(RPUSH + LPOP)
Library System example to use Redis Sets.
Sets in Redis are unordered collections of unique elements, which makes them great for handling
book categories, borrowed books, etc.

📚 Redis Library Case Study with Set Operations

We have two students borrowing books:

SADD student1_books "Book_A" "Book_B" "Book_C"

SADD student2_books "Book_B" "Book_C" "Book_D"

Now:

student1_books = { Book_A, Book_B, Book_C }

student2_books = { Book_B, Book_C, Book_D }

🔹 1. Intersection (common books borrowed by both students)

SINTER student1_books student2_books

✅ Output:

{ Book_B, Book_C }

📌 Meaning: Both Student1 and Student2 borrowed Book_B and Book_C.

🔹 2. Union (all unique books borrowed by either student)

SUNION student1_books student2_books

✅ Output:

{ Book_A, Book_B, Book_C, Book_D }

📌 Meaning: Across both students, the library records all distinct borrowed books.

🔹 3. Difference (books borrowed by Student1 but not by Student2)

SDIFF student1_books student2_books

✅ Output:
{ Book_A }

📌 Meaning: Book_A was borrowed only by Student1.

Similarly, books unique to Student2:

SDIFF student2_books student1_books

✅ Output:

{ Book_D }

📌 Summary (Library System with Sets)

 SINTER → Common books borrowed by both students.

 SUNION → All books borrowed (removes duplicates).

 SDIFF → Books borrowed by one student but not the other.


Got it 👍 You want to see how we can design an Employee Database using Redis Hashes.
Since Redis is a key-value store, we typically model each employee as a Hash, where fields are stored
as key-value pairs.

📂 Employee Database in Redis (with Hashes)

Example: Insert Employee Records

# Employee 1

HSET employee:101 name "Alice" age "25" department "HR" salary "35000" likes "3"

# Employee 2

HSET employee:102 name "Bob" age "30" department "IT" salary "60000" likes "5"

# Employee 3

HSET employee:103 name "Charlie" age "28" department "Finance" salary "45000" likes "2"

# Employee 4

HSET employee:104 name "David" age "35" department "IT" salary "75000" likes "4"

# Employee 5

HSET employee:105 name "Eva" age "22" department "HR" salary "30000" likes "1"

✅ Fetch Full Employee Record

HGETALL employee:102

Output:

1) "name" 2) "Bob"

3) "age" 4) "30"

5) "department" 6) "IT"

7) "salary" 8) "60000"
9) "likes" 10) "5"

✅ Fetch Specific Field

HGET employee:101 department

Output:

"HR"

✅ Update Salary

HINCRBY employee:102 salary 5000

Now Bob’s salary = 65000.

✅ Store Skills Separately

Since Hashes cannot store arrays directly, we use a Set or List for skills.

SADD employee:101:skills "Excel" "Recruitment"

SADD employee:102:skills "Java" "MongoDB" "[Link]"

SADD employee:103:skills "Accounting" "Excel"

SADD employee:104:skills "Python" "AWS"

SADD employee:105:skills "Communication" "Excel"

📌 Queries with Redis Hash + Skills

Find all skills of Bob

SMEMBERS employee:102:skills

Output:

1) "Java"

2) "MongoDB"

3) "[Link]"

Check if Alice knows Excel

SISMEMBER employee:101:skills "Excel"

Output:

(integer) 1 # Yes

List all employees (just IDs)


KEYS employee:*

📌 Summary

 Each employee → stored as a Redis Hash (employee:<id>).

 Skills → stored as a Set (employee:<id>:skills).

 Advantages:

o Fast lookups (HGETALL, HGET)

o Easy updates (HINCRBY)

o Flexible skills handling via Sets


Pub/Sub is used in Redis when we want real-time notifications — e.g., HR system notifies when a
new employee is added, or when someone’s salary is updated.

📂 Employee Database + Pub/Sub

We already have employees stored as Hashes:

HSET employee:101 name "Alice" age "25" department "HR" salary "35000" likes "3"

HSET employee:102 name "Bob" age "30" department "IT" salary "60000" likes "5"

And skills as Sets:

SADD employee:101:skills "Excel" "Recruitment"

SADD employee:102:skills "Java" "MongoDB" "[Link]"

🔹 1. Publisher: Sending Notifications

Example: New Employee Added

PUBLISH employee_notifications "New employee Alice (ID:101) added to HR department"

Example: Salary Updated

PUBLISH employee_notifications "Salary updated for Bob (ID:102) to 60000"

🔹 2. Subscriber: Listening for Notifications

Any service (HR dashboard, payroll system, etc.) can subscribe to the channel:

SUBSCRIBE employee_notifications

✅ Output when publisher sends messages:

1) "message"

2) "employee_notifications"

3) "New employee Alice (ID:101) added to HR department"

1) "message"

2) "employee_notifications"

3) "Salary updated for Bob (ID:102) to 60000"


📌 Use Case in Library/Employee System

 HR/Admin Service publishes changes:

o “New employee added”

o “Salary increment done”

o “Employee resigned”

 Other Systems (Subscribers) react in real time:

o Payroll system updates salary records.

o Attendance system links new employees.

o Notifications service alerts employees.

✅ In short:

 Hashes → store employee data.

 Sets → store skills.

 Pub/Sub → broadcast updates to other systems in real time.


Excellent 👍 Let’s now extend the Employee Database in Redis with Transactions.

Redis transactions let us execute a group of commands atomically — either all succeed, or none.
We use:

 MULTI → Start transaction

 EXEC → Execute all queued commands

 DISCARD → Cancel transaction

 WATCH → Optimistic locking (check for changes before committing)

📂 Employee Database (Hash + Skills)

Current Data

HSET employee:101 name "Alice" age "25" department "HR" salary "35000"

HSET employee:102 name "Bob" age "30" department "IT" salary "60000"

SADD employee:101:skills "Excel" "Recruitment"

SADD employee:102:skills "Java" "MongoDB" "[Link]"

🔹 Example 1: Add New Employee (Atomic Insert)

MULTI

HSET employee:103 name "Charlie" age "28" department "Finance" salary "45000"

SADD employee:103:skills "Accounting" "Excel"

PUBLISH employee_notifications "New Employee Charlie (ID:103) added"

EXEC

✅ Result:

 Employee Hash created

 Skills added

 Notification published

 All executed together

🔹 Example 2: Salary Increment (Safe Update)


Suppose we want to increase Bob’s salary by 5000.
We use WATCH to prevent conflicts (if another process changes the salary while we are updating).

WATCH employee:102

MULTI

HINCRBY employee:102 salary 5000

PUBLISH employee_notifications "Bob's salary incremented by 5000"

EXEC

✅ If no one modified employee:102 after WATCH, the transaction succeeds.


❌ If another client changed it → EXEC will fail, and we retry.

🔹 Example 3: Remove Employee (Atomic Delete)

If Bob resigns, remove both Hash and Skills atomically:

MULTI

DEL employee:102

DEL employee:102:skills

PUBLISH employee_notifications "Employee Bob (ID:102) removed from database"

EXEC

✅ Ensures both main record and skills are deleted together.

📌 Summary

 Transactions in Employee DB help ensure consistency.

 Use Cases:

o Adding a new employee (Hash + Skills + Notification)

o Salary increments (safe with WATCH)

o Deleting employee (Hash + Skills removed together)


step-by-step Redis transaction log for the Salary Increment case (Employee: Bob, ID:102).

📂 Initial State in Redis

HGETALL employee:102

Output:

1) "name" 2) "Bob"

3) "age" 4) "30"

5) "department" 6) "IT"

7) "salary" 8) "60000"

So, Bob’s salary = 60000.

🔹 Step 1: WATCH the Key

We tell Redis: “If this key changes, abort my transaction.”

WATCH employee:102

🔹 Step 2: Start Transaction

MULTI

Redis replies:

OK

🔹 Step 3: Queue Commands

Now we queue multiple operations (nothing executes yet).

HINCRBY employee:102 salary 5000

PUBLISH employee_notifications "Bob's salary incremented by 5000"

Redis replies after each:

QUEUED

QUEUED

🔹 Step 4: Execute Transaction

EXEC
If no other client modified employee:102 since the WATCH, Redis executes both commands
atomically:

✅ Output:

1) (integer) 65000 # New salary after increment

2) (integer) 1 # 1 subscriber got the notification

📂 Final State in Redis

HGET employee:102 salary

Output:

"65000"

And any subscriber listening to employee_notifications sees:

"Bob's salary incremented by 5000"

📌 What happened step by step

1. WATCH guarded the key (employee:102).

2. MULTI began the transaction.

3. HINCRBY (salary update) and PUBLISH (notification) were queued.

4. EXEC executed them atomically → salary updated + notification sent.

5. If another client had changed employee:102 after WATCH, then EXEC would return null,
meaning transaction failed, and we’d retry.
step-by-step Redis transaction log for adding a new employee (Charlie, ID:103) with Hash + Skills +
Notification.

📂 Goal

 Add Charlie’s main details in a Hash

 Add his skills in a Set

 Publish a notification to HR

🔹 Step 1: Start Transaction

MULTI

Response:

OK

🔹 Step 2: Queue Commands

HSET employee:103 name "Charlie" age "28" department "Finance" salary "45000"

SADD employee:103:skills "Accounting" "Excel"

PUBLISH employee_notifications "New employee Charlie (ID:103) added"

Responses:

QUEUED

QUEUED

QUEUED

👉 Nothing executed yet — just queued.

🔹 Step 3: Execute Transaction

EXEC

Responses (all run atomically):

1) (integer) 4 # 4 fields set in employee:103 hash

2) (integer) 2 # 2 skills added to employee:103:skills set

3) (integer) 1 # 1 subscriber got the notification

📂 Final State in Redis


Employee Hash

HGETALL employee:103

Output:

1) "name" 2) "Charlie"

3) "age" 4) "28"

5) "department" 6) "Finance"

7) "salary" 8) "45000"

Employee Skills

SMEMBERS employee:103:skills

Output:

1) "Accounting"

2) "Excel"

Subscriber Output

If HR dashboard is subscribed:

SUBSCRIBE employee_notifications

They see:

"New employee Charlie (ID:103) added"

📌 Step-by-Step Summary

1. MULTI → Begin transaction.

2. HSET → Insert employee record.

3. SADD → Insert skills.

4. PUBLISH → Notify HR.

5. EXEC → Execute all atomically → ✅ Charlie added completely or not at all.


Awesome 🚀 Let’s extend the Ticket Booking Example with $group + $sort to find the top
customer(s) who booked the most tickets.

🎟 Collection Reminder

[Link]([

"booking_id": 1,

"customer": "Alice",

"tickets": [

{ "movie": "Avengers", "seat": "A1", "price": 300 },

{ "movie": "Avengers", "seat": "A2", "price": 300 }

],

"booking_date": ISODate("2025-09-15T10:00:00Z")

},

"booking_id": 2,

"customer": "Bob",

"tickets": [

{ "movie": "Batman", "seat": "B1", "price": 250 }

],

"booking_date": ISODate("2025-09-16T12:30:00Z")

},

"booking_id": 3,

"customer": "Charlie",

"tickets": [

{ "movie": "Avengers", "seat": "C1", "price": 300 },

{ "movie": "Avengers", "seat": "C2", "price": 300 },

{ "movie": "Avengers", "seat": "C3", "price": 300 }

],
"booking_date": ISODate("2025-09-17T18:45:00Z")

])

🔹 $group + $sort → Top Customers by Ticket Count

We want to count how many tickets each customer booked and then sort them in descending order.

[Link]([

{ $unwind: "$tickets" }, // Break array into individual tickets

{ $group: { _id: "$customer", totalTickets: { $sum: 1 } } },

{ $sort: { totalTickets: -1 } }, // Highest first

{ $limit: 1 } // Top customer only

])

✅ Output:

{ "_id": "Charlie", "totalTickets": 3 }

📌 Meaning: Charlie booked the most tickets (3 tickets).

🔹 Variation: Show Top 2 Customers

[Link]([

{ $unwind: "$tickets" },

{ $group: { _id: "$customer", totalTickets: { $sum: 1 } } },

{ $sort: { totalTickets: -1 } },

{ $limit: 2 }

])

✅ Output:

{ "_id": "Charlie", "totalTickets": 3 }

{ "_id": "Alice", "totalTickets": 2 }

📌 Summary

 $unwind → expands tickets array

 $group → counts tickets per customer


 $sort → orders by highest bookings

 $limit → restricts to top N customers

examples of MongoDB evaluation operators ($mod, $regex, $text, $where) with sample datasets
and queries. I’ll give you small datasets, queries, and outputs for each operator.

📌 Evaluation Operator Examples

1. $mod Example
Dataset:

{ "_id": 1, "order_id": 101, "amount": 5000 },

{ "_id": 2, "order_id": 102, "amount": 3000 },

{ "_id": 3, "order_id": 103, "amount": 4200 }

Query: Find orders where amount is divisible by 1000.

[Link]({ amount: { $mod: [1000, 0] } })

✅ Output:

{ "_id": 1, "order_id": 101, "amount": 5000 },

{ "_id": 2, "order_id": 102, "amount": 3000 }

2. $regex Example

Dataset:

{ "_id": 1, "name": "Anil Kumar" },

{ "_id": 2, "name": "Priya Sharma" },

{ "_id": 3, "name": "Arjun Mehta" }

Query: Find customers whose name starts with "A".

[Link]({ name: { $regex: /^A/, $options: "i" } })

✅ Output:

{ "_id": 1, "name": "Anil Kumar" },

{ "_id": 3, "name": "Arjun Mehta" }

3. $text Example

⚠️Requires a text index first.


Dataset:

{ "_id": 1, "review": "This course is excellent for beginners." },

{ "_id": 2, "review": "The course content is very detailed." },

{ "_id": 3, "review": "Excellent teaching style and examples." }

Create index:

[Link]({ review: "text" })

Query: Search for the word "excellent".

[Link]({ $text: { $search: "excellent" } })

✅ Output:

{ "_id": 1, "review": "This course is excellent for beginners." },

{ "_id": 3, "review": "Excellent teaching style and examples." }

4. $where Example

Dataset:

{ "_id": 1, "product": "Laptop", "price": 45000 },

{ "_id": 2, "product": "Phone", "price": 25000 },

{ "_id": 3, "product": "Tablet", "price": 30000 }

Query: Find products where price > 30000.

[Link]({ $where: "[Link] > 30000" })

✅ Output:

{ "_id": 1, "product": "Laptop", "price": 45000 }

🔥 Summary:
 $mod → Numeric divisibility check.

 $regex → Pattern matching for strings.

 $text → Full-text search.

 $where → JS expressions for custom conditions.

MongoDB offers robust support for geospatial data and queries, allowing you to efficiently store,
index, and query location-based information. This functionality is crucial for applications like
mapping, navigation, location-based services, and geographic analysis.

Key Concepts:

 Geospatial Data Formats:

o GeoJSON: The recommended format for representing geospatial data in MongoDB. It


supports various geometry types like Point, LineString, Polygon, MultiPoint,
MultiLineString, MultiPolygon, and GeometryCollection, interpreting them on a
spherical surface (like the Earth).

o Legacy Coordinate Pairs: An older format for representing points on a two-


dimensional Euclidean plane (flat surface).

 Geospatial Indexes:
o 2dsphere Index: Designed for queries that interpret geometry on a sphere. It
supports all GeoJSON geometry types and is recommended for most geospatial
applications.

o 2d Index: Supports queries that interpret geometry on a flat surface (using legacy
coordinate pairs) and some spherical queries, although 2dsphere is preferred for
spherical queries for accuracy.

 Geospatial Query Operators: MongoDB provides a rich set of operators for performing
geospatial queries:

o $geoWithin: Finds documents with geospatial data entirely contained within a


specified shape (e.g., a polygon or a circle).

o $geoIntersects: Finds documents with geospatial data that intersects with a specified
GeoJSON geometry.

o $near / $nearSphere: Finds documents with geospatial data closest to a specified


point. $nearSphere is specifically for spherical queries and is generally more
accurate.

o $minDistance / $maxDistance: Used with $near or $nearSphere to specify a


minimum and/or maximum distance for the search.

Example Usage (using GeoJSON Point and 2dsphere index):

1. Create a 2dsphere index:

[Link]({ location: "2dsphere" })

2. Insert a document with GeoJSON Point:

[Link]({
name: "Eiffel Tower",
location: {
type: "Point",
coordinates: [2.2945, 48.8584] // [longitude, latitude]
}
})

3. Find locations near a point:


[Link]({
location: {
$nearSphere: {
$geometry: {
type: "Point",
coordinates: [2.2945, 48.8584]
},
$maxDistance: 1000 // in meters
}
}
})

📌 Dataset Reminder

{ "_id": 1, "name": "Arjun", "marks": 85 }, // binary: 1010101

{ "_id": 2, "name": "Meera", "marks": 72 }, // binary: 1001000

{ "_id": 3, "name": "Rahul", "marks": 90 }, // binary: 1011010

{ "_id": 4, "name": "Priya", "marks": 60 } // binary: 0111100

👉 In binary, each bit position represents a power of 2:

 bit 0 → 1

 bit 1 → 2

 bit 2 → 4

 bit 3 → 8

 bit 4 → 16

 bit 5 → 32

 bit 6 → 64

1️⃣ $bitsAllSet

[Link]({ marks: { $bitsAllSet: [1, 3] } })

 This means: both bit 1 and bit 3 must be 1.

 Bit 1 = value 2, Bit 3 = value 8.

👉 Check each:
 85 (1010101) → bit 1 = 0 ❌

 72 (1001000) → bit 1 = 0 ❌

 90 (1011010) → bit 1 = 1, bit 3 = 1 ✅

 60 (0111100) → bit 1 = 0 ❌

✅ Matches: Rahul (90)

2️⃣ $bitsAnySet

[Link]({ marks: { $bitsAnySet: [4, 5] } })

 This means: at least one of bit 4 or bit 5 must be 1.

 Bit 4 = 16, Bit 5 = 32.

👉 Check:

 85 → has 16 (bit 4 = 1) ✅

 72 → has 64 + 8 (so bit 5 = 1) ✅

 90 → has 32 + 16 (both bits 4 & 5 = 1) ✅

 60 → has 32 + 16 (both bits 4 & 5 = 1) ✅

✅ Matches: All students

3️⃣ $bitsAllClear

[Link]({ marks: { $bitsAllClear: [0, 1] } })

 This means: bit 0 and bit 1 must both be 0.

 Bit 0 = 1, Bit 1 = 2.

👉 Check:

 85 → binary ends in 01 (bit0=1, bit1=0) ❌

 72 → binary ends in 1000 (bit0=0, bit1=0) ✅

 90 → binary ends in 1010 (bit0=0, bit1=1) ❌

 60 → binary ends in 1100 (bit0=0, bit1=0) ✅

✅ Matches: Meera (72), Priya (60)

4️⃣ $bitsAnyClear

[Link]({ marks: { $bitsAnyClear: [2, 3] } })

 This means: at least one of bit 2 or bit 3 must be 0.


 Bit 2 = 4, Bit 3 = 8.

👉 Check:

 85 → bits 2+3 = 01 → one is 0 ✅

 72 → bits 2+3 = 00 → both 0 ✅

 90 → bits 2+3 = 10 → one is 0 ✅

 60 → bits 2+3 = 11 → both 1 ❌

✅ Matches: Arjun (85), Meera (72), Rahul (90)

🔑 Summary

 $bitsAllSet → require all specified bits = 1

 $bitsAnySet → require at least one bit = 1

 $bitsAllClear → require all specified bits = 0

 $bitsAnyClear → require at least one bit = 0


Q1. Redis (Sets)

a. Insert 6 unique participants

SADD participants "Alice" "Bob" "Charlie" "David" "Emma" "Frank"

b. Move 2 random participants from participants → winners

SPOP participants 2 # removes 2 random participants

SADD winners "Alice" "Charlie" # (example moved participants)

c. Merge participants and winners → all_entries

SUNIONSTORE all_entries participants winners

d. Add 2 new participants into all_entries

SADD all_entries "Grace" "Henry"

e. Remove 1 random participant each from all_entries & winners

SPOP all_entries

SPOP winners

Q2. Redis (Lists)

a. Insert values into queue

RPUSH queue 11 22 33 44 55 22

b. Insert 99 between 33 and 44

LINSERT queue AFTER 33 99

c. Remove last 2 values from queue → insert into backup

RPOPLPUSH queue backup

RPOPLPUSH queue backup


d. Show last 3 values from queue

LRANGE queue -3 -1

e. Update first value in backup to 77

LSET backup 0 77

Q3. MongoDB (Orders Collection)

Dataset:

{ "orderId": 101, "customerName": "Anil", "orderValue": 5000,

"items": [2,1,4], "discounts": [5,10,0], "finalBill": [4750,4500,4000] },

{ "orderId": 102, "customerName": "Priya", "orderValue": 3000,

"items": [1,2,3], "discounts": [0,5,10], "finalBill": [3000,2850,2700] }

a. Insert records

[Link]([...]) // as above

b. Find orders with value > 4000 (show Order ID, Customer Name)

[Link]({ orderValue: { $gt: 4000 } }, { _id:0, orderId:1, customerName:1 })

c. Update Order Value of ID 102 → 3500

[Link]({ orderId: 102 }, { $set: { orderValue: 3500 } })

d. Delete Priya’s order

[Link]({ customerName: "Priya" })

e. Add new item to Priya’s order

[Link](

{ customerName: "Priya" },

{ $push: { items: 5, discounts: 15, finalBill: 2500 } }

Q4. MongoDB (Queries on Orders)

a. Find orders where OrderValue ≥ 3000 AND CustomerName ≠ "Priya"

[Link]({ $and: [ { orderValue: { $gte: 3000 } }, { customerName: { $ne: "Priya" } } ] })


b. Average Final Bill per customer

[Link]([

{ $unwind: "$finalBill" },

{ $group: { _id: "$customerName", avgBill: { $avg: "$finalBill" } } }

])

c. Check if Items is array type

[Link]({ items: { $type: "array" } })

(or)

[Link]({ $expr: { $isArray: "$items" } })

d. Customers with OrderValue divisible by 2

[Link]({ $expr: { $eq: [ { $mod: ["$orderValue", 2] }, 0 ] } })

e. Add computed field HighValue

[Link]([

{ $addFields: { HighValue: { $cond: [ { $gt: ["$orderValue", 4000] }, true, false ] } } }

])

Q5. MongoDB (Vehicle Service Collection)

Sample document:

order_id: "SR1001",

customer: "Arjun",

services: [

{ service_name: "Oil Change", cost: 1200, status: "done" },

{ service_name: "Brake Check", cost: 800, status: "pending" }

],

paid: false

a. Insert 2 service bookings

[Link]([

order_id: "SR1001", customer: "Arjun",


services: [

{ service_name: "Oil Change", cost: 1200, status: "done" },

{ service_name: "Brake Check", cost: 800, status: "pending" }

], paid: false

},

order_id: "SR1002", customer: "Meera",

services: [

{ service_name: "Battery Replacement", cost: 1500, status: "done" },

{ service_name: "Tyre Check", cost: 600, status: "pending" }

], paid: true

])

b. Retrieve all customers with any service status = "done"

[Link]({ services: { $elemMatch: { status: "done" } } })

c. Update docs → set "priority":"high" if any cost > 1000

[Link](

{ $expr: { $gt: [ { $max: "$[Link]" }, 1000 ] } },

{ $set: { priority: "high" } }

d. Average service cost per customer

[Link]([

{ $unwind: "$services" },

{ $group: { _id: "$customer", avgCost: { $avg: "$[Link]" } } }

])

e. Find customers where service name starts with "B"

[Link]({ "services.service_name": { $regex: /^B/ } })


Q1. Redis – Hashes (Library borrowed_books)

a. Insert 5 book records

HSET borrowed_books 101 "DBMS" 102 "OS" 103 "Networks" 104 "AI" 105 "NoSQL"

✅ Output:

(integer) 5

b. Move 2 books (e.g., 101, 103) → returned_books

HSET returned_books 101 "DBMS" 103 "Networks"

HDEL borrowed_books 101 103

✅ Output:

(integer) 2 # from HDEL

c. Create new hash all_books (merged)

HSET all_books 101 "DBMS" 102 "OS" 103 "Networks" 104 "AI" 105 "NoSQL"

✅ Output:

(integer) 5

d. Add 2 new books

HSET all_books 106 "Cloud" 107 "Big Data"

✅ Output:

(integer) 2

e. Remove 1 book (say 102) from both borrowed_books & all_books

HDEL borrowed_books 102

HDEL all_books 102

✅ Output:

(integer) 1
Q2. Redis – Lists (stack)

a. Insert values

RPUSH stack 5 10 15 20 25

✅ Output:

(integer) 5

b. Insert 12 before 15

LINSERT stack BEFORE 15 12

✅ Output:

(integer) 6

c. Pop last 2 values → move to archive

RPOPLPUSH stack archive

RPOPLPUSH stack archive

✅ Output:

"25"

"20"

d. Show first 2 values

LRANGE stack 0 1

✅ Output:

1) "5"

2) "10"

e. Check length of archive

LLEN archive

✅ Output:

(integer) 2

Q3. MongoDB – Student Marks Database

Dataset:

{ "roll": 201, "name": "Arjun", "marks": [85,90,78], "attendance": [25,26,27] },

{ "roll": 202, "name": "Meera", "marks": [60,72,68], "attendance": [24,25,23] }

]
a. Insert records

[Link]([...])

✅ Output:

{ acknowledged: true, insertedIds: [ ObjectId(...), ObjectId(...) ] }

b. Read all student records

[Link]().pretty()

✅ Output:

{ "roll":201,"name":"Arjun","marks":[85,90,78],"attendance":[25,26,27]}

{ "roll":202,"name":"Meera","marks":[60,72,68],"attendance":[24,25,23]}

c. Update Meera’s marks (add 85)

[Link]({name:"Meera"}, { $push: { marks: 85 } })

✅ Output:

{ acknowledged: true, matchedCount: 1, modifiedCount: 1 }

d. Delete Arjun

[Link]({ roll: 201 })

✅ Output:

{ acknowledged: true, deletedCount: 1 }

e. Find student by roll number (202)

[Link]({ roll: 202 })

✅ Output:

{ "roll":202,"name":"Meera","marks":[60,72,68,85],"attendance":[24,25,23]}

Q4. MongoDB – Queries

a. Total marks per student

[Link]([

{ $project: { name:1, totalMarks: { $sum:"$marks" } } }

])

✅ Output:

{ "name":"Arjun","totalMarks":253 }

{ "name":"Meera","totalMarks":285 }

b. Students NOT "Meera"


[Link]({ name: { $ne: "Meera" } })

✅ Output:

{ "roll":201,"name":"Arjun","marks":[85,90,78],"attendance":[25,26,27]}

c. Sort by total attendance descending

[Link]([

{ $project: { name:1, totalAttendance: { $sum:"$attendance" } } },

{ $sort: { totalAttendance:-1 } }

])

✅ Output:

{ "name":"Arjun","totalAttendance":78 }

{ "name":"Meera","totalAttendance":72 }

d. Find students with total marks ≥ 220

[Link]([

{ $match: { $expr: { $gte: [ { $sum:"$marks" }, 220 ] } } }

])

✅ Output:

{ "name":"Arjun","marks":[85,90,78] }

{ "name":"Meera","marks":[60,72,68,85] }

e. Add computed field Result

[Link]([

{ $project: { name:1, avgMarks: { $avg:"$marks" },

Result: { $cond:[ { $gte:[ { $avg:"$marks" },70 ] }, "Pass","Fail"] } } }

])

✅ Output:

{ "name":"Arjun","avgMarks":84.33,"Result":"Pass" }

{ "name":"Meera","avgMarks":71.25,"Result":"Pass" }

Q5. MongoDB – Online Course Enrollment

Sample dataset:

{ enroll_id:"ENR5001", student:"Meera",

courses:[
{ course_name:"Python", grade:"A", fee:4500 },

{ course_name:"Data Science", grade:"B", fee:6000 }

], completed:true }

a. Insert 2 enrollments

[Link]([

{ enroll_id:"ENR5001", student:"Meera", courses:[

{course_name:"Python", grade:"A", fee:4500},

{course_name:"Data Science", grade:"B", fee:6000}], completed:true },

{ enroll_id:"ENR5002", student:"Arjun", courses:[

{course_name:"AI", grade:"C", fee:4000},

{course_name:"Big Data", grade:"A", fee:5500}], completed:false }

])

✅ Output:

{ acknowledged:true, insertedIds:[...] }

b. Retrieve courses where fee > 5000

[Link]([

{ $unwind:"$courses" },

{ $match: { "[Link]": { $gt:5000 } } },

{ $project: { _id:0, "courses.course_name":1 } }

])

✅ Output:

{ "course_name":"Data Science" }

{ "course_name":"Big Data" }

c. Set completed:true for ENR5002

[Link]({ enroll_id:"ENR5002" }, { $set:{ completed:true } })

✅ Output:

{ acknowledged:true, matchedCount:1, modifiedCount:1 }

d. Total fee of all courses for Meera

[Link]([

{ $match:{ student:"Meera" } },

{ $unwind:"$courses" },
{ $group:{ _id:"$student", totalFee:{ $sum:"$[Link]" } } }

])

✅ Output:

{ "_id":"Meera", "totalFee":10500 }

e. Students with any course grade "A"

[Link]({ "[Link]":"A" })

✅ Output:

{ "student":"Meera", "courses":[{ "course_name":"Python","grade":"A","fee":4500}, ...] }

{ "student":"Arjun", "courses":[{ "course_name":"Big Data","grade":"A","fee":5500}, ...] }

Great question 👍 Let’s go step by step on the MongoDB $mod operator (with all possible use cases +
outputs).

🔹 MongoDB $mod Operator

 $mod finds the remainder of dividing one number by another.

 Format:

{ field: { $mod: [ divisor, remainder ] } }

 It checks whether field % divisor == remainder.

✅ Example 1 – Find Even Numbers

Suppose collection numbers:

{ "num": 10 },

{ "num": 15 },
{ "num": 20 },

{ "num": 23 }

👉 Query: Find all even numbers (num % 2 == 0)

[Link]({ num: { $mod: [2, 0] } })

Output:

{ "num": 10 }

{ "num": 20 }

✅ Example 2 – Find Odd Numbers

👉 Query: Find all odd numbers (num % 2 == 1)

[Link]({ num: { $mod: [2, 1] } })

Output:

{ "num": 15 }

{ "num": 23 }

✅ Example 3 – Multiples of 5

👉 Query: Find numbers divisible by 5 (num % 5 == 0)

[Link]({ num: { $mod: [5, 0] } })

Output:

{ "num": 10 }

{ "num": 15 }

{ "num": 20 }

✅ Example 4 – Custom Remainder Check

👉 Query: Find numbers where remainder is 3 when divided by 5 (num % 5 == 3)

[Link]({ num: { $mod: [5, 3] } })

Output:

{ "num": 23 }

✅ Example 5 – With $expr (Dynamic Field Check)


Suppose collection students:

{ "roll": 201, "name": "Arjun", "totalMarks": 253 },

{ "roll": 202, "name": "Meera", "totalMarks": 220 },

{ "roll": 203, "name": "Rahul", "totalMarks": 285 }

👉 Query: Find students where totalMarks divisible by 2

[Link]({

$expr: { $eq: [ { $mod: ["$totalMarks", 2] }, 0 ] }

})

Output:

{ "roll": 202, "name": "Meera", "totalMarks": 220 }

✅ Example 6 – With Aggregation Pipeline

👉 Query: Add a computed field "EvenOrOdd" using $mod:

[Link]([

{ $project: {

num: 1,

EvenOrOdd: {

$cond: [ { $eq: [ { $mod: ["$num", 2] }, 0 ] }, "Even", "Odd" ]

])

Output:

{ "num": 10, "EvenOrOdd": "Even" }

{ "num": 15, "EvenOrOdd": "Odd" }

{ "num": 20, "EvenOrOdd": "Even" }

{ "num": 23, "EvenOrOdd": "Odd" }

🔑 Summary
 $mod: [2,0] → even numbers

 $mod: [2,1] → odd numbers

 $mod: [n,0] → multiples of n

 $mod: [n,r] → numbers giving remainder r when divided by n

 Can be used in find(), $expr, and aggregation pipelines

Got it 👍 Let’s break down $geometry in MongoDB geospatial queries.

🔹 What is $geometry?

 $geometry specifies the GeoJSON object (Point, LineString, Polygon, etc.) you want to use in
a geospatial query.

 It defines the shape + coordinates.

 Used with operators like:

o $near / $nearSphere

o $geoWithin

o $geoIntersects

🔹 GeoJSON Structures

1. Point

{ "type": "Point", "coordinates": [ <longitude>, <latitude> ] }

Example:
{ "type": "Point", "coordinates": [77.5946, 12.9716] } // Bangalore

2. LineString

{ "type": "LineString", "coordinates": [ [ <lng1>, <lat1> ], [ <lng2>, <lat2> ], ... ] }

Example:

{ "type": "LineString", "coordinates": [[77.59,12.97],[80.27,13.08]] } // Bangalore→Chennai

3. Polygon

"type": "Polygon",

"coordinates": [

[ [ <lng1>, <lat1> ], [ <lng2>, <lat2> ], [ <lng3>, <lat3> ], [ <lng1>, <lat1> ] ]

👉 Last coordinate must equal the first (closed shape).

Example (triangle – Bangalore–Chennai–Hyderabad):

"type": "Polygon",

"coordinates": [[

[77.59,12.97], [80.27,13.08], [78.49,17.38], [77.59,12.97]

]]

🔹 Examples Using $geometry

1. $near with $geometry

Find places near Bangalore:

[Link]({

location: {

$near: {

$geometry: { type: "Point", coordinates: [77.59, 12.97] },

$maxDistance: 500000
}

})

2. $geoWithin with $geometry

Find places inside polygon:

[Link]({

location: {

$geoWithin: {

$geometry: {

type: "Polygon",

coordinates: [[

[77.59,12.97],[80.27,13.08],[78.49,17.38],[77.59,12.97]

]]

})

3. $geoIntersects with $geometry

Find places intersecting with a rectangle:

[Link]({

location: {

$geoIntersects: {

$geometry: {

type: "Polygon",

coordinates: [[

[72,10],[85,10],[85,20],[72,20],[72,10]

]]

}
}

})

🔑 Summary

 $geometry = Defines the GeoJSON object (Point, LineString, Polygon).

 Always used inside $near, $geoWithin, $geoIntersects, $nearSphere.

 Essential for geospatial queries.

Nice 👌 You’ve written a perfect $expr query. Let’s carefully explain what it does step by step.

📌 Query:

[Link](

$expr: {

$gt: [ "$salary", { $multiply: ["$age", 2000] } ]

}
},

{ _id: 0, name: 1, salary: 1, age: 1 }

🔹 Step 1 – $expr

 Tells MongoDB to evaluate expressions (not just compare with fixed values).

 Allows usage of aggregation operators like $gt, $multiply, $add, $mod, etc.

🔹 Step 2 – $gt

 $gt: [X, Y] means X > Y.

 Here: "$salary" > { $multiply: ["$age", 2000] }.

🔹 Step 3 – { $multiply: ["$age", 2000] }

 This computes a value = age * 2000.

 Example: If age = 25, then 25 * 2000 = 50000.

🔹 Step 4 – Condition

 The query checks:


Is salary > (age × 2000)?

So for each document, MongoDB calculates age * 2000 and then compares it with salary.

🔹 Step 5 – Projection

{ _id: 0, name: 1, salary: 1, age: 1 }

 This hides _id and shows only name, salary, age.

✅ Example Dataset:

{ "name":"Alice", "salary":60000, "age":25 }

{ "name":"Bob", "salary":30000, "age":20 }

{ "name":"Charlie","salary":90000, "age":35 }

📌 Evaluations:

1. Alice → age*2000 = 25*2000 = 50000 → salary=60000 > 50000 ✅


2. Bob → age*2000 = 20*2000 = 40000 → salary=30000 > 40000 ❌

3. Charlie → age*2000 = 35*2000 = 70000 → salary=90000 > 70000 ✅

✅ Output:

{ "name":"Alice", "salary":60000, "age":25 }

{ "name":"Charlie", "salary":90000, "age":35 }

🔑 In Simple Words

👉 This query finds employees whose salary is greater than 2000 × their age.

 Uses $expr for field-to-expression comparison.

 Uses $multiply to calculate age × 2000.

 Uses $gt to check if salary is bigger than that value.

 Projects only name, salary, age.

sample dataset that includes:

1. An array field

2. A nested document field

Here’s a clean example you can directly use 👇

📌 Sample Dataset – Employees Collection

"empId": 101,
"name": "Alice",

"age": 25,

"salary": 55000,

"skills": ["Java", "Python", "MongoDB"], // ✅ array field

"address": { // ✅ nested document

"city": "Bangalore",

"state": "Karnataka",

"pincode": 560001

},

"empId": 102,

"name": "Bob",

"age": 30,

"salary": 65000,

"skills": ["JavaScript", "[Link]", "React"],

"address": {

"city": "Chennai",

"state": "Tamil Nadu",

"pincode": 600001

},

"empId": 103,

"name": "Charlie",

"age": 28,

"salary": 48000,

"skills": ["C++", "Go", "Docker"],

"address": {

"city": "Hyderabad",

"state": "Telangana",
"pincode": 500001

🔹 Features in this dataset:

 Array field: skills


Example: "skills": ["Java", "Python", "MongoDB"]

 Nested document field: address


Example:

 "address": {

 "city": "Bangalore",

 "state": "Karnataka",

 "pincode": 560001

 }

🔹 Example Queries on this Dataset:

1. Find employees who know MongoDB (array search):

[Link]({ skills: "MongoDB" })

2. Find employees from Chennai (nested document search):

[Link]({ "[Link]": "Chennai" })

3. Project only name & skills:

[Link]({}, { _id:0, name:1, skills:1 })


The $cond operator in MongoDB's aggregation framework provides conditional logic, similar to an
"if-then-else" statement. It evaluates a boolean expression and returns one of two specified
expressions based on whether the boolean expression is true or false. [1]

Syntax:

$cond supports two syntaxes: Lohghand Syntax.

{ $cond: { if: <boolean-expression>, then: <true-case>, else: <false-case> } }

shorthand syntax.

{ $cond: [ <boolean-expression>, <true-case>, <false-case> ] }

Explanation of Components:

 &lt;boolean-expression&gt;: This is an expression that evaluates to a boolean value (true or


false). It can involve comparison operators ($eq, $gt, $lt, etc.), logical operators ($and, $or,
$not), or other expressions that yield a boolean result.

 &lt;true-case&gt;: This is the expression that $cond evaluates and returns if the &lt;boolean-
expression&gt; evaluates to true.

 &lt;false-case&gt;: This is the expression that $cond evaluates and returns if the &lt;boolean-
expression&gt; evaluates to false.

Usage in Aggregation Pipelines:

$cond is commonly used within various aggregation pipeline stages, such as:

 $project: To create new fields or modify existing ones based on conditional logic.

 $addFields: Similar to $project, for adding new fields with conditional values.
 $group: To conditionally include or exclude values when grouping documents.

 $set: In update operations within aggregation pipelines, to conditionally set field values.

Example:

Consider a collection of products with price and quantity fields. You want to calculate a
discountedPrice based on the quantity: if quantity is 100 or more, apply a 0.5% discount; otherwise,
apply a 0.75% discount.

[Link]([
{
$project: {
_id: 0,
name: "$name",
originalPrice: "$price",
discountedPrice: {
$cond: {
if: { $gte: ["$quantity", 100] },
then: { $multiply: ["$price", 0.995] }, // 0.5% discount
else: { $multiply: ["$price", 0.9925] } // 0.75% discount
}
}
}
}
])

[Link]

Let’s build an example for a YouTube-like database where we’ll use $lookup in MongoDB
Aggregation.
🎬 Example Database

We’ll create two collections:

1. channels collection

{ "_id": 1, "name": "TechZone", "category": "Technology" },

{ "_id": 2, "name": "FoodiesHub", "category": "Cooking" },

{ "_id": 3, "name": "TravelWorld", "category": "Travel" }

2. videos collection

{ "_id": 101, "title": "Latest Gadgets 2025", "views": 120000, "channel_id": 1 },

{ "_id": 102, "title": "AI Tools Explained", "views": 95000, "channel_id": 1 },

{ "_id": 103, "title": "Street Food in Delhi", "views": 150000, "channel_id": 2 },

{ "_id": 104, "title": "Italian Pasta Recipe", "views": 78000, "channel_id": 2 },

{ "_id": 105, "title": "Top 10 Europe Destinations", "views": 89000, "channel_id": 3 }

🔍 Query 1: Join channels with videos

We want each channel along with its videos.

[Link]([

$lookup: {

from: "videos", // target collection

localField: "_id", // channel id in channels

foreignField: "channel_id",// channel id in videos

as: "channel_videos" // output array field

])

✅ Output
[

"_id": 1,

"name": "TechZone",

"category": "Technology",

"channel_videos": [

{ "_id": 101, "title": "Latest Gadgets 2025", "views": 120000, "channel_id": 1 },

{ "_id": 102, "title": "AI Tools Explained", "views": 95000, "channel_id": 1 }

},

"_id": 2,

"name": "FoodiesHub",

"category": "Cooking",

"channel_videos": [

{ "_id": 103, "title": "Street Food in Delhi", "views": 150000, "channel_id": 2 },

{ "_id": 104, "title": "Italian Pasta Recipe", "views": 78000, "channel_id": 2 }

},

"_id": 3,

"name": "TravelWorld",

"category": "Travel",

"channel_videos": [

{ "_id": 105, "title": "Top 10 Europe Destinations", "views": 89000, "channel_id": 3 }

🔍 Query 2: Find each channel with total video count & total views

We add $unwind, $group.


[Link]([

$lookup: {

from: "videos",

localField: "_id",

foreignField: "channel_id",

as: "channel_videos"

},

{ $unwind: "$channel_videos" },

$group: {

_id: "$name",

total_videos: { $sum: 1 },

total_views: { $sum: "$channel_videos.views" }

])

✅ Output

{ "_id": "TechZone", "total_videos": 2, "total_views": 215000 },

{ "_id": "FoodiesHub", "total_videos": 2, "total_views": 228000 },

{ "_id": "TravelWorld", "total_videos": 1, "total_views": 89000 }

👉 This is how we can use $lookup in MongoDB Aggregation for a YouTube-style database.

 YouTube database with a third collection: comments.


Now we’ll see how to use $lookup twice to join channels → videos → comments.
🎬 Collections

1. channels

{ "_id": 1, "name": "TechZone", "category": "Technology" },

{ "_id": 2, "name": "FoodiesHub", "category": "Cooking" },

{ "_id": 3, "name": "TravelWorld", "category": "Travel" }

2. videos

{ "_id": 101, "title": "Latest Gadgets 2025", "views": 120000, "channel_id": 1 },

{ "_id": 102, "title": "AI Tools Explained", "views": 95000, "channel_id": 1 },

{ "_id": 103, "title": "Street Food in Delhi", "views": 150000, "channel_id": 2 },

{ "_id": 104, "title": "Italian Pasta Recipe", "views": 78000, "channel_id": 2 },

{ "_id": 105, "title": "Top 10 Europe Destinations", "views": 89000, "channel_id": 3 }

3. comments

{ "_id": 201, "video_id": 101, "user": "Alice", "text": "Amazing review!" },

{ "_id": 202, "video_id": 101, "user": "Bob", "text": "Very helpful, thanks." },

{ "_id": 203, "video_id": 103, "user": "Charlie", "text": "Now I’m hungry 😋" },

{ "_id": 204, "video_id": 105, "user": "Diana", "text": "Great travel tips!" }

🔍 Query: Get channels → videos → comments

[Link]([

$lookup: {

from: "videos",

localField: "_id",

foreignField: "channel_id",

as: "videos"
}

},

{ $unwind: "$videos" },

$lookup: {

from: "comments",

localField: "videos._id",

foreignField: "video_id",

as: "[Link]"

},

$group: {

_id: "$_id",

name: { $first: "$name" },

category: { $first: "$category" },

videos: { $push: "$videos" }

])

✅ Output

"_id": 1,

"name": "TechZone",

"category": "Technology",

"videos": [

"_id": 101,

"title": "Latest Gadgets 2025",


"views": 120000,

"channel_id": 1,

"comments": [

{ "_id": 201, "video_id": 101, "user": "Alice", "text": "Amazing review!" },

{ "_id": 202, "video_id": 101, "user": "Bob", "text": "Very helpful, thanks." }

},

"_id": 102,

"title": "AI Tools Explained",

"views": 95000,

"channel_id": 1,

"comments": []

},

"_id": 2,

"name": "FoodiesHub",

"category": "Cooking",

"videos": [

"_id": 103,

"title": "Street Food in Delhi",

"views": 150000,

"channel_id": 2,

"comments": [

{ "_id": 203, "video_id": 103, "user": "Charlie", "text": "Now I’m hungry 😋" }

},

{
"_id": 104,

"title": "Italian Pasta Recipe",

"views": 78000,

"channel_id": 2,

"comments": []

},

"_id": 3,

"name": "TravelWorld",

"category": "Travel",

"videos": [

"_id": 105,

"title": "Top 10 Europe Destinations",

"views": 89000,

"channel_id": 3,

"comments": [

{ "_id": 204, "video_id": 105, "user": "Diana", "text": "Great travel tips!" }

👉 Now we have nested results:

 A channel contains its videos

 Each video contains its comments


👉 Find total number of videos and total number of comments for each channel.

🔍 Query: Channel Summary with Video & Comment Counts

[Link]([

$lookup: {

from: "videos",

localField: "_id",

foreignField: "channel_id",

as: "videos"

},

{ $unwind: "$videos" },

$lookup: {

from: "comments",

localField: "videos._id",

foreignField: "video_id",

as: "video_comments"

},

$group: {

_id: "$name",

total_videos: { $sum: 1 },

total_comments: { $sum: { $size: "$video_comments" } }

])
✅ Output

{ "_id": "TechZone", "total_videos": 2, "total_comments": 2 },

{ "_id": "FoodiesHub", "total_videos": 2, "total_comments": 1 },

{ "_id": "TravelWorld", "total_videos": 1, "total_comments": 1 }

🔎 Explanation

1. First $lookup → fetches videos for each channel.

2. $unwind → breaks the videos array so we can count properly.

3. Second $lookup → fetches comments for each video.

4. $group → groups back by channel name and calculates:

o total_videos → count of videos per channel

o total_comments → total comments across all its videos

Awesome 🚀 Let’s now find the most commented video per channel using our YouTube dataset.

🎬 Collections Recap

 channels → channel info

 videos → videos belong to channels

 comments → comments belong to videos

🔍 Query: Most Commented Video per Channel

[Link]([

$lookup: {

from: "videos",

localField: "_id",

foreignField: "channel_id",

as: "videos"
}

},

{ $unwind: "$videos" },

$lookup: {

from: "comments",

localField: "videos._id",

foreignField: "video_id",

as: "video_comments"

},

$addFields: {

comment_count: { $size: "$video_comments" }

},

$sort: { comment_count: -1 } // sort by comments (descending)

},

$group: {

_id: "$name", // group by channel

most_commented_video: { $first: "$[Link]" },

comment_count: { $first: "$comment_count" }

])

✅ Output

{ "_id": "TechZone", "most_commented_video": "Latest Gadgets 2025", "comment_count": 2 },


{ "_id": "FoodiesHub", "most_commented_video": "Street Food in Delhi", "comment_count": 1 },

{ "_id": "TravelWorld", "most_commented_video": "Top 10 Europe Destinations",


"comment_count": 1 }

🔎 Explanation

1. First $lookup → join channels with their videos.

2. Unwind videos → process one video at a time.

3. Second $lookup → fetch comments for each video.

4. $addFields → add comment_count (size of comments array).

5. Sort by comment_count (highest first).

6. Group by channel and pick the first video (highest comments per channel).

Top N videos across all channels ranked by the number of comments.

🔍 Query: Top N Most Commented Videos (Across All Channels)

Here, let’s fetch the top 3 videos with the highest number of comments.

[Link]([

$lookup: {

from: "comments",

localField: "_id",

foreignField: "video_id",

as: "video_comments"

},

$addFields: {

comment_count: { $size: "$video_comments" }

}
},

$lookup: {

from: "channels",

localField: "channel_id",

foreignField: "_id",

as: "channel"

},

{ $unwind: "$channel" },

$project: {

_id: 0,

video_title: "$title",

channel_name: "$[Link]",

comment_count: 1

},

{ $sort: { comment_count: -1 } }, // sort by comments (desc)

{ $limit: 3 } // pick top 3

])

✅ Output

{ "video_title": "Latest Gadgets 2025", "channel_name": "TechZone", "comment_count": 2 },

{ "video_title": "Street Food in Delhi", "channel_name": "FoodiesHub", "comment_count": 1 },

{ "video_title": "Top 10 Europe Destinations", "channel_name": "TravelWorld", "comment_count": 1


}

🔎 Explanation
1. First $lookup → attach comments to each video.

2. $addFields → calculate comment_count.

3. Second $lookup → join back with channels to get channel name.

4. $project → display only useful fields (video_title, channel_name, comment_count).

5. $sort → order by comment_count descending.

6. $limit → restrict to top N results.

👉 Now you can easily rank videos by engagement across the whole platform.

Nice 🔥 Let’s now combine views + comments to rank the Top N videos in a YouTube-style database.
🔍 Query: Top N Videos Ranked by Comments and Views

We’ll fetch the Top 3 videos sorted first by comment_count (desc), then by views (desc).

[Link]([

$lookup: {

from: "comments",

localField: "_id",

foreignField: "video_id",

as: "video_comments"

},

$addFields: {

comment_count: { $size: "$video_comments" }

},

$lookup: {

from: "channels",

localField: "channel_id",

foreignField: "_id",

as: "channel"

},

{ $unwind: "$channel" },

$project: {

_id: 0,

video_title: "$title",

channel_name: "$[Link]",

views: 1,
comment_count: 1

},

{ $sort: { comment_count: -1, views: -1 } }, // multi-sort

{ $limit: 3 }

])

✅ Output

"video_title": "Latest Gadgets 2025",

"channel_name": "TechZone",

"views": 120000,

"comment_count": 2

},

"video_title": "Street Food in Delhi",

"channel_name": "FoodiesHub",

"views": 150000,

"comment_count": 1

},

"video_title": "Top 10 Europe Destinations",

"channel_name": "TravelWorld",

"views": 89000,

"comment_count": 1

🔎 Explanation

1. $lookup (comments) → attach comments to each video.


2. $addFields → count comments (comment_count).

3. $lookup (channels) → attach channel name.

4. $project → select only needed fields.

5. $sort → sort by comments first, then views.

6. $limit → pick top N (here 3).

👉 This ranking helps find videos with strong engagement (comments), and among them, prioritize
those with higher views.

Great idea ⚡ Let’s build a channel leaderboard that ranks channels by total views + total comments.
🔍 Query: Channel Leaderboard (Total Views + Comments)

[Link]([

$lookup: {

from: "videos",

localField: "_id",

foreignField: "channel_id",

as: "videos"

},

{ $unwind: "$videos" },

$lookup: {

from: "comments",

localField: "videos._id",

foreignField: "video_id",

as: "video_comments"

},

$group: {

_id: "$name",

total_views: { $sum: "$[Link]" },

total_comments: { $sum: { $size: "$video_comments" } }

},

$addFields: {

engagement_score: { $add: ["$total_views", "$total_comments"] }

},
{ $sort: { engagement_score: -1 } }

])

✅ Output

"_id": "FoodiesHub",

"total_views": 228000,

"total_comments": 1,

"engagement_score": 228001

},

"_id": "TechZone",

"total_views": 215000,

"total_comments": 2,

"engagement_score": 215002

},

"_id": "TravelWorld",

"total_views": 89000,

"total_comments": 1,

"engagement_score": 89001

🔎 Explanation

1. Join with videos → get all videos for each channel.

2. Unwind videos → process one video at a time.

3. Join with comments → get all comments for each video.

4. Group by channel → sum up views and comments.

5. Add engagement score → total_views + total_comments.


6. Sort → rank channels by overall engagement.

👉 Now you have a leaderboard of channels ranked by combined views + comments.

Perfect 👍 Let’s take it one step deeper and calculate average views per video and average comments
per video for each channel.
🔍 Query: Channel Averages (Views & Comments per Video)

[Link]([

$lookup: {

from: "videos",

localField: "_id",

foreignField: "channel_id",

as: "videos"

},

{ $unwind: "$videos" },

$lookup: {

from: "comments",

localField: "videos._id",

foreignField: "video_id",

as: "video_comments"

},

$group: {

_id: "$name",

total_views: { $sum: "$[Link]" },

total_comments: { $sum: { $size: "$video_comments" } },

total_videos: { $sum: 1 }

},

$project: {

_id: 1,

total_videos: 1,
avg_views_per_video: { $divide: ["$total_views", "$total_videos"] },

avg_comments_per_video: { $divide: ["$total_comments", "$total_videos"] }

},

{ $sort: { avg_views_per_video: -1 } }

])

✅ Output

"_id": "FoodiesHub",

"total_videos": 2,

"avg_views_per_video": 114000,

"avg_comments_per_video": 0.5

},

"_id": "TechZone",

"total_videos": 2,

"avg_views_per_video": 107500,

"avg_comments_per_video": 1

},

"_id": "TravelWorld",

"total_videos": 1,

"avg_views_per_video": 89000,

"avg_comments_per_video": 1

🔎 Explanation

1. Join with videos → get all videos per channel.


2. Unwind videos → process video by video.

3. Join with comments → fetch comments per video.

4. Group by channel → compute totals:

o total_views

o total_comments

o total_videos

5. Project averages:

o avg_views_per_video = total_views ÷ total_videos

o avg_comments_per_video = total_comments ÷ total_videos

6. Sort by average views for ranking.

👉 This gives you deeper insight into engagement efficiency per video instead of just totals.

Awesome 🚀 Let’s now build a custom weighted engagement score so we can rank channels not just
by raw views or comments, but by a formula that balances both.

🎯 Formula

Let’s define an Engagement Score as:

Engagement Score = (Average Views per Video * 0.7) + (Average Comments per Video * 0.3)

👉 You can adjust the weights (0.7 and 0.3) depending on whether you want to value views more or
comments more.

🔍 Query: Weighted Engagement Score per Channel

[Link]([

$lookup: {

from: "videos",

localField: "_id",

foreignField: "channel_id",

as: "videos"

}
},

{ $unwind: "$videos" },

$lookup: {

from: "comments",

localField: "videos._id",

foreignField: "video_id",

as: "video_comments"

},

$group: {

_id: "$name",

total_views: { $sum: "$[Link]" },

total_comments: { $sum: { $size: "$video_comments" } },

total_videos: { $sum: 1 }

},

$project: {

total_videos: 1,

avg_views_per_video: { $divide: ["$total_views", "$total_videos"] },

avg_comments_per_video: { $divide: ["$total_comments", "$total_videos"] }

},

$addFields: {

engagement_score: {

$add: [

{ $multiply: ["$avg_views_per_video", 0.7] },

{ $multiply: ["$avg_comments_per_video", 0.3] }


]

},

{ $sort: { engagement_score: -1 } }

])

✅ Output

"_id": "FoodiesHub",

"total_videos": 2,

"avg_views_per_video": 114000,

"avg_comments_per_video": 0.5,

"engagement_score": 79800.15

},

"_id": "TechZone",

"total_videos": 2,

"avg_views_per_video": 107500,

"avg_comments_per_video": 1,

"engagement_score": 75250.3

},

"_id": "TravelWorld",

"total_videos": 1,

"avg_views_per_video": 89000,

"avg_comments_per_video": 1,

"engagement_score": 62300.3

]
🔎 Explanation

1. Join videos → bring in each channel’s videos.

2. Unwind → process one video at a time.

3. Join comments → bring in comments for each video.

4. Group by channel → get totals.

5. Compute averages → avg_views_per_video, avg_comments_per_video.

6. Add engagement score → weighted formula using $multiply and $add.

7. Sort by score → highest engagement score first.

👉 Now you can rank channels by engagement quality, not just raw numbers.

Nice choice 🚀 Let’s now calculate the Top N videos per channel ranked by the weighted engagement
score within each channel.

🎯 Formula Reminder

Engagement Score = (Views * 0.7) + (Comment Count * 0.3)

We’ll fetch Top 2 videos per channel.

🔍 Query: Top N Videos per Channel by Engagement Score

[Link]([

$lookup: {

from: "comments",

localField: "_id",

foreignField: "video_id",

as: "video_comments"

},

$addFields: {
comment_count: { $size: "$video_comments" },

engagement_score: {

$add: [

{ $multiply: ["$views", 0.7] },

{ $multiply: [{ $size: "$video_comments" }, 0.3] }

},

$lookup: {

from: "channels",

localField: "channel_id",

foreignField: "_id",

as: "channel"

},

{ $unwind: "$channel" },

$sort: { "[Link]": 1, engagement_score: -1 }

},

$group: {

_id: "$[Link]",

top_videos: {

$push: {

title: "$title",

views: "$views",

comment_count: "$comment_count",

engagement_score: "$engagement_score"

}
}

},

$project: {

_id: 1,

top_videos: { $slice: ["$top_videos", 2] } // take Top 2

])

✅ Output

"_id": "FoodiesHub",

"top_videos": [

"title": "Street Food in Delhi",

"views": 150000,

"comment_count": 1,

"engagement_score": 105000.3

},

"title": "Italian Pasta Recipe",

"views": 78000,

"comment_count": 0,

"engagement_score": 54600

},

{
"_id": "TechZone",

"top_videos": [

"title": "Latest Gadgets 2025",

"views": 120000,

"comment_count": 2,

"engagement_score": 84000.6

},

"title": "AI Tools Explained",

"views": 95000,

"comment_count": 0,

"engagement_score": 66500

},

"_id": "TravelWorld",

"top_videos": [

"title": "Top 10 Europe Destinations",

"views": 89000,

"comment_count": 1,

"engagement_score": 62300.3

🔎 Explanation

1. Lookup comments → fetch all comments for each video.


2. Add comment_count & engagement_score → apply formula.

3. Lookup channels → attach channel name.

4. Sort → order videos by engagement score (descending), grouped by channel.

5. Group by channel → gather all videos into an array.

6. Project with $slice → select top N (here 2) videos per channel.

👉 This way, you can see the top-performing videos inside each channel.

Sure! Let’s go operator by operator and generate practical MongoDB examples for arrays, including
update operators, positional operators, and array aggregation expressions. I’ll keep it simple and
clear.
1️⃣ Array Update Operators

a) $addToSet

Adds elements only if they don’t already exist.

[Link](

{ name: "Alice" },

{ $addToSet: { courses: "Math" } }

 Adds "Math" to courses array only if it’s not already there.

b) $pop

Removes first (-1) or last (1) element.

[Link](

{ name: "Alice" },

{ $pop: { courses: 1 } } // removes last element

c) $pull

Removes all instances of a value or matching a query.

[Link](

{ name: "Alice" },

{ $pull: { courses: "History" } } // removes "History" from courses

d) $pullAll

Removes multiple values from an array.

[Link](

{ name: "Alice" },

{ $pullAll: { courses: ["Math", "Science"] } }

e) $push (with modifiers)


Add elements with control over position, sorting, and slicing.

[Link](

{ name: "Alice" },

$push: {

courses: { $each: ["Physics", "Chemistry"], $position: 0 }

 Adds "Physics" and "Chemistry" at the beginning of the array.

2️⃣ Positional Operators

a) $

Update the first matching element in an array.

[Link](

{ "[Link]": "Math" },

{ $set: { "grades.$.score": 95 } } // updates first Math score

b) $[]

Update all elements in an array.

[Link](

{ name: "Alice" },

{ $set: { "grades.$[].passed": true } } // marks all grades as passed

c) $[<identifier>]

Update elements matching a condition.

[Link](

{ name: "Alice" },

{ $set: { "grades.$[elem].score": 100 } },


{ arrayFilters: [{ "[Link]": "Science" }] }

 Updates score to 100 only for "Science" subject.

3️⃣ Array Aggregation Expression Operators

a) $arrayElemAt

Get element at a specific index.

[Link]([

{ $project: { first_course: { $arrayElemAt: ["$courses", 0] } } }

])

b) $concatArrays

Concatenate arrays.

[Link]([

{ $project: { all_courses: { $concatArrays: ["$courses", ["English"]] } } }

])

c) $filter

Select elements matching a condition.

[Link]([

{ $project: { passed_courses: { $filter: { input: "$grades", as: "g", cond: { $gte: ["$$[Link]",
60] } } } } }

])

d) $isArray

Check if a field is an array.

[Link]([

{ $project: { isArray: { $isArray: "$courses" } } }

])

e) $map
Transform array elements.

[Link]([

{ $project: { upper_courses: { $map: { input: "$courses", as: "c", in: { $toUpper: "$$c" } } } } }

])

f) $range

Generate an array of numbers.

[Link]([

{ $project: { numbers: { $range: [1, 6] } } } // [1,2,3,4,5]

])

g) $reverseArray

Reverse an array.

[Link]([

{ $project: { reversed_courses: { $reverseArray: "$courses" } } }

])

h) $slice

Return subset of an array.

[Link]([

{ $project: { first_two_courses: { $slice: ["$courses", 2] } } }

])

i) $sortArray

Sort array elements.

[Link]([

{ $project: { sorted_scores: { $sortArray: { input: "$[Link]", sortBy: 1 } } } }

])

j) $zip

Combine multiple arrays element-wise.


[Link]([

{ $project: { courses_and_scores: { $zip: { inputs: ["$courses", "$[Link]"] } } } }

])

 Combines [courses] and [scores] into pairs.

students, courses, and grades, and show examples of all array operators in action.

1️⃣ Sample Dataset

students collection

"_id": 1,

"name": "Alice",

"courses": ["Math", "History", "Science"],

"grades": [

{ "subject": "Math", "score": 85 },

{ "subject": "History", "score": 70 },

{ "subject": "Science", "score": 90 }

},

"_id": 2,

"name": "Bob",

"courses": ["Math", "English", "Art"],

"grades": [

{ "subject": "Math", "score": 60 },

{ "subject": "English", "score": 75 },

{ "subject": "Art", "score": 80 }

]
2️⃣ Array Update Operators Examples

a) $addToSet → Add “PE” only if it doesn’t exist

[Link](

{ name: "Alice" },

{ $addToSet: { courses: "PE" } }

b) $pop → Remove last course

[Link](

{ name: "Bob" },

{ $pop: { courses: 1 } }

c) $pull → Remove “History”

[Link](

{ name: "Alice" },

{ $pull: { courses: "History" } }

d) $pullAll → Remove multiple courses

[Link](

{ name: "Bob" },

{ $pullAll: { courses: ["Math", "Art"] } }

e) $push with $each → Add multiple courses at start

[Link](

{ name: "Alice" },

{ $push: { courses: { $each: ["Art", "Music"], $position: 0 } } }

3️⃣ Positional Operators Examples

a) $ → Update first matching grade

[Link](
{ "[Link]": "Math" },

{ $set: { "grades.$.score": 95 } }

b) $[] → Update all grades to passed

[Link](

{ name: "Alice" },

{ $set: { "grades.$[].passed": true } }

c) $[<identifier>] → Update only Science grade

[Link](

{ name: "Alice" },

{ $set: { "grades.$[g].score": 100 } },

{ arrayFilters: [{ "[Link]": "Science" }] }

4️⃣ Array Aggregation Expression Examples

a) $arrayElemAt → Get first course

[Link]([

{ $project: { first_course: { $arrayElemAt: ["$courses", 0] } } }

])

b) $concatArrays → Add “PE” course

[Link]([

{ $project: { all_courses: { $concatArrays: ["$courses", ["PE"]] } } }

])

c) $filter → Grades ≥ 80

[Link]([

{ $project: { high_grades: { $filter: { input: "$grades", as: "g", cond: { $gte: ["$$[Link]", 80] } } } } }

])

d) $isArray → Check if courses is array

[Link]([

{ $project: { is_courses_array: { $isArray: "$courses" } } }


])

e) $map → Uppercase courses

[Link]([

{ $project: { upper_courses: { $map: { input: "$courses", as: "c", in: { $toUpper: "$$c" } } } } }

])

f) $range → Generate numbers

[Link]([

{ $project: { numbers: { $range: [1, 6] } } }

])

g) $reverseArray → Reverse courses

[Link]([

{ $project: { reversed_courses: { $reverseArray: "$courses" } } }

])

h) $slice → First 2 courses

[Link]([

{ $project: { first_two_courses: { $slice: ["$courses", 2] } } }

])

i) $sortArray → Sort grades

[Link]([

{ $project: { sorted_scores: { $sortArray: { input: "$[Link]", sortBy: 1 } } } }

])

j) $zip → Combine courses and scores

[Link]([

{ $project: { courses_and_scores: { $zip: { inputs: ["$courses", "$[Link]"] } } } }

])

✅ With this dataset, you can practice every array operator in both updates and aggregation.

Let’s create a single aggregation pipeline that demonstrates many array operators together on our
students dataset. This will act as a practical cheat sheet.
Cheat Sheet Aggregation Pipeline

[Link]([

$project: {

// 1️⃣ Original courses

original_courses: "$courses",

// 2️⃣ First course using $arrayElemAt

first_course: { $arrayElemAt: ["$courses", 0] },

// 3️⃣ Concatenate extra courses using $concatArrays

all_courses: { $concatArrays: ["$courses", ["PE", "Music"]] },

// 4️⃣ Filter grades with score >= 80 using $filter

high_grades: {

$filter: {

input: "$grades",

as: "g",

cond: { $gte: ["$$[Link]", 80] }

},

// 5️⃣ Check if courses is an array using $isArray

is_courses_array: { $isArray: "$courses" },

// 6️⃣ Uppercase all courses using $map

upper_courses: {

$map: {

input: "$courses",

as: "c",

in: { $toUpper: "$$c" }


}

},

// 7️⃣ Generate a number range using $range

number_sequence: { $range: [1, 6] },

// 8️⃣ Reverse courses using $reverseArray

reversed_courses: { $reverseArray: "$courses" },

// 9️⃣ Slice first two courses using $slice

first_two_courses: { $slice: ["$courses", 2] },

// 🔟 Sort grades scores using $sortArray

sorted_scores: { $sortArray: { input: "$[Link]", sortBy: 1 } },

// 1️⃣1️⃣ Combine courses and scores using $zip

courses_and_scores: { $zip: { inputs: ["$courses", "$[Link]"] } }

])

✅ What This Pipeline Does

Operator Example Use in Pipeline

$arrayElemAt Returns first course

$concatArrays Adds extra courses

$filter Keeps grades ≥ 80

$isArray Checks if courses is an array

$map Uppercases each course

$range Generates numbers [1,2,3,4,5]

$reverseArray Reverses the course array


Operator Example Use in Pipeline

$slice Returns first 2 courses

$sortArray Sorts grades scores

$zip Pairs courses with scores

This single aggregation lets you see most array aggregation operators in action without needing
multiple queries.

Bit wise Operators:

Great — let’s carefully unpack this MongoDB query:

[Link]({

accessFlags: { $bitsAllClear: [3] }

})
🔎 Step 1: Operator Meaning

 $bitsAllClear: [3]
→ This checks if all bits at the given positions are 0.

 Here [3] means bit position 3 (counting from the right, 0-based).

So the query finds all documents where bit 3 = 0 in the field accessFlags.

🔎 Step 2: Binary Representation

Let’s recall bit positions (0-based indexing):

Bit: 3 2 1 0

Value: 8 4 2 1

So:

 Bit 0 → 1

 Bit 1 → 2

 Bit 2 → 4

 Bit 3 → 8

Here we’re checking bit 3 = Manage Payroll permission (value 8).

🔎 Step 3: Dataset Example

Suppose we have:

{ "_id": 1, "name": "Alice", "accessFlags": 1 }, // 0001

{ "_id": 2, "name": "Bob", "accessFlags": 3 }, // 0011

{ "_id": 3, "name": "Charlie", "accessFlags": 5 }, // 0101

{ "_id": 4, "name": "David", "accessFlags": 13 }, // 1101

{ "_id": 5, "name": "Eve", "accessFlags": 8 } // 1000

🔎 Step 4: Apply Condition

We want bit 3 = 0.

 Alice (0001) → bit 3 = 0 ✅


 Bob (0011) → bit 3 = 0 ✅

 Charlie (0101) → bit 3 = 0 ✅

 David (1101) → bit 3 = 1 ❌

 Eve (1000) → bit 3 = 1 ❌

✅ Query Result

{ "_id": 1, "name": "Alice", "accessFlags": 1 },

{ "_id": 2, "name": "Bob", "accessFlags": 3 },

{ "_id": 3, "name": "Charlie", "accessFlags": 5 }

👉 In simple words:
This query finds employees who do not have Manage Payroll permission (because that’s the bit at
position 3).

Employee dataset with bitwise operations inside the MongoDB aggregation pipeline.

MongoDB provides bitwise aggregation operators:

 $bitAnd → Bitwise AND

 $bitOr → Bitwise OR

 $bitXor → Bitwise XOR

 $bitNot → Bitwise NOT

Employee Dataset (same as before)

{ "_id": 1, "name": "Alice", "accessFlags": 1 }, // 0001 -> View

{ "_id": 2, "name": "Bob", "accessFlags": 3 }, // 0011 -> View + Edit

{ "_id": 3, "name": "Charlie", "accessFlags": 5 }, // 0101 -> View + Approve Leave

{ "_id": 4, "name": "David", "accessFlags": 13 }, // 1101 -> View + Approve Leave + Manage Payroll

{ "_id": 5, "name": "Eve", "accessFlags": 8 } // 1000 -> Manage Payroll

]
Aggregation Examples

1. Check if an employee has Approve Leave (bit 2 → 4)

[Link]([

$project: {

name: 1,

accessFlags: 1,

hasApproveLeave: {

$cond: [

{ $eq: [{ $bitAnd: ["$accessFlags", 4] }, 4] },

true,

false

])

✅ Output:

{ "_id": 1, "name": "Alice", "accessFlags": 1, "hasApproveLeave": false },

{ "_id": 2, "name": "Bob", "accessFlags": 3, "hasApproveLeave": false },

{ "_id": 3, "name": "Charlie", "accessFlags": 5, "hasApproveLeave": true },

{ "_id": 4, "name": "David", "accessFlags": 13, "hasApproveLeave": true },

{ "_id": 5, "name": "Eve", "accessFlags": 8, "hasApproveLeave": false }

2. Compute combined permissions of all employees (using $group + $bitOr)

[Link]([

$group: {

_id: null,
combinedPermissions: { $bitOr: ["$accessFlags"] }

])

✅ Output:

{ "_id": null, "combinedPermissions": 15 }

👉 15 in binary is 1111, meaning across all employees, all permissions are used (View, Edit, Approve
Leave, Manage Payroll).

3. Find employees who have only View Reports (no other bits set)

[Link]([

$project: {

name: 1,

accessFlags: 1,

onlyViewReports: {

$eq: ["$accessFlags", 1]

])

✅ Output:

{ "_id": 1, "name": "Alice", "accessFlags": 1, "onlyViewReports": true },

{ "_id": 2, "name": "Bob", "accessFlags": 3, "onlyViewReports": false },

{ "_id": 3, "name": "Charlie", "accessFlags": 5, "onlyViewReports": false },

{ "_id": 4, "name": "David", "accessFlags": 13, "onlyViewReports": false },

{ "_id": 5, "name": "Eve", "accessFlags": 8, "onlyViewReports": false }

]
4. Flip all bits of accessFlags (using $bitNot)

[Link]([

$project: {

name: 1,

accessFlags: 1,

flippedFlags: { $bitNot: "$accessFlags" }

])

✅ Output (depends on bit length, but showing 32-bit signed int results):

{ "_id": 1, "name": "Alice", "accessFlags": 1, "flippedFlags": -2 },

{ "_id": 2, "name": "Bob", "accessFlags": 3, "flippedFlags": -4 },

{ "_id": 3, "name": "Charlie", "accessFlags": 5, "flippedFlags": -6 },

{ "_id": 4, "name": "David", "accessFlags": 13, "flippedFlags": -14 },

{ "_id": 5, "name": "Eve", "accessFlags": 8, "flippedFlags": -9 }

✨ With these, you can not only query permissions using bitwise filters but also analyze and compute
them in aggregations.

Got it 👍 — let’s design a bitwise employee dataset and then use aggregation pipeline with bitwise
operators to analyze it.

📂 Sample Employee Dataset

Each employee has accessFlags (integer), where bits represent permissions:


Bit Value Permission

0 1 View Reports

1 2 Edit Reports

2 4 Approve Leave

3 8 Manage Payroll

Documents

{ "_id": 1, "name": "Alice", "accessFlags": 1 }, // 0001 -> View

{ "_id": 2, "name": "Bob", "accessFlags": 3 }, // 0011 -> View + Edit

{ "_id": 3, "name": "Charlie", "accessFlags": 5 }, // 0101 -> View + Approve Leave

{ "_id": 4, "name": "David", "accessFlags": 13 }, // 1101 -> View + Approve Leave + Payroll

{ "_id": 5, "name": "Eve", "accessFlags": 8 } // 1000 -> Payroll only

📊 Aggregation Examples

1. Show which employees have Approve Leave (bit 2)

[Link]([

$project: {

name: 1,

accessFlags: 1,

hasApproveLeave: {

$cond: [

{ $eq: [{ $bitAnd: ["$accessFlags", 4] }, 4] },

true,

false

])
✅ Output:

{ "name": "Alice", "accessFlags": 1, "hasApproveLeave": false },

{ "name": "Bob", "accessFlags": 3, "hasApproveLeave": false },

{ "name": "Charlie", "accessFlags": 5, "hasApproveLeave": true },

{ "name": "David", "accessFlags": 13, "hasApproveLeave": true },

{ "name": "Eve", "accessFlags": 8, "hasApproveLeave": false }

2. Count how many employees have each permission

[Link]([

$group: {

_id: null,

viewReports: {

$sum: { $cond: [{ $eq: [{ $bitAnd: ["$accessFlags", 1] }, 1] }, 1, 0] }

},

editReports: {

$sum: { $cond: [{ $eq: [{ $bitAnd: ["$accessFlags", 2] }, 2] }, 1, 0] }

},

approveLeave: {

$sum: { $cond: [{ $eq: [{ $bitAnd: ["$accessFlags", 4] }, 4] }, 1, 0] }

},

managePayroll: {

$sum: { $cond: [{ $eq: [{ $bitAnd: ["$accessFlags", 8] }, 8] }, 1, 0] }

])

✅ Output:

[
{

"viewReports": 3,

"editReports": 1,

"approveLeave": 2,

"managePayroll": 2

3. Find employees with only one permission

[Link]([

$project: {

name: 1,

accessFlags: 1,

onlyOnePermission: {

$eq: [

{ $bitAnd: ["$accessFlags", "$accessFlags"] }, // itself

{ $pow: [2, { $floor: { $log2: "$accessFlags" } }] } // nearest power of 2

])

✅ Output:

{ "name": "Alice", "accessFlags": 1, "onlyOnePermission": true },

{ "name": "Bob", "accessFlags": 3, "onlyOnePermission": false },

{ "name": "Charlie","accessFlags": 5, "onlyOnePermission": false },

{ "name": "David", "accessFlags": 13, "onlyOnePermission": false },

{ "name": "Eve", "accessFlags": 8, "onlyOnePermission": true }

]
4. Get combined permissions of all employees

[Link]([

$group: {

_id: null,

allPermissions: { $bitOr: ["$accessFlags"] }

])

✅ Output:

{ "_id": null, "allPermissions": 15 }

👉 15 in binary = 1111, meaning across all employees, every permission is covered.

⚡ So with aggregation + bitwise, you can:

 Test if employees have specific permissions

 Count how many employees hold each permission

 Find “only-one-permission” users

 Merge permissions across the organization

practice set using our employee + bitwise permissions dataset.

📂 Dataset Reminder

{ "_id": 1, "name": "Alice", "accessFlags": 1 }, // 0001 -> View

{ "_id": 2, "name": "Bob", "accessFlags": 3 }, // 0011 -> View + Edit


{ "_id": 3, "name": "Charlie", "accessFlags": 5 }, // 0101 -> View + Approve Leave

{ "_id": 4, "name": "David", "accessFlags": 13 }, // 1101 -> View + Approve Leave + Payroll

{ "_id": 5, "name": "Eve", "accessFlags": 8 } // 1000 -> Payroll

Permissions:

 Bit 0 → View Reports (1)

 Bit 1 → Edit Reports (2)

 Bit 2 → Approve Leave (4)

 Bit 3 → Manage Payroll (8)

📝 Practice Questions

Q1. Find employees who have Approve Leave permission.

[Link]([

$match: {

accessFlags: { $bitsAllSet: [2] } // bit 2 = 4

},

{ $project: { _id: 0, name: 1, accessFlags: 1 } }

])

✅ Output:

{ "name": "Charlie", "accessFlags": 5 },

{ "name": "David", "accessFlags": 13 }

Q2. Count how many employees can Manage Payroll.

[Link]([

$group: {

_id: null,
payrollCount: {

$sum: { $cond: [{ $eq: [{ $bitAnd: ["$accessFlags", 8] }, 8] }, 1, 0] }

])

✅ Output:

{ "_id": null, "payrollCount": 2 }

Q3. Show each employee with a boolean field hasEditReports.

[Link]([

$project: {

name: 1,

hasEditReports: {

$cond: [

{ $eq: [{ $bitAnd: ["$accessFlags", 2] }, 2] },

true,

false

])

✅ Output:

{ "name": "Alice", "hasEditReports": false },

{ "name": "Bob", "hasEditReports": true },

{ "name": "Charlie", "hasEditReports": false },


{ "name": "David", "hasEditReports": false },

{ "name": "Eve", "hasEditReports": false }

Q4. Find employees with only one permission.

[Link]([

$match: {

$expr: {

$in: ["$accessFlags", [1, 2, 4, 8]] // powers of 2 = only one bit set

},

{ $project: { _id: 0, name: 1, accessFlags: 1 } }

])

✅ Output:

{ "name": "Alice", "accessFlags": 1 },

{ "name": "Eve", "accessFlags": 8 }

Q5. Get combined permissions across all employees.

[Link]([

$group: {

_id: null,

allPermissions: { $bitOr: ["$accessFlags"] }

])

✅ Output:
[

{ "_id": null, "allPermissions": 15 }

👉 15 = 1111 (binary) → All 4 permissions are represented across employees.

⚡ These 5 cover:

1. Filtering with $bitsAllSet

2. Counting with $group

3. Adding computed boolean fields

4. Finding “single-permission” users

5. Combining permissions across the dataset

📂 Employee Dataset (Reminder)

{ "_id": 1, "name": "Alice", "accessFlags": 1 }, // 0001 -> View

{ "_id": 2, "name": "Bob", "accessFlags": 3 }, // 0011 -> View + Edit

{ "_id": 3, "name": "Charlie", "accessFlags": 5 }, // 0101 -> View + Approve Leave


{ "_id": 4, "name": "David", "accessFlags": 13 }, // 1101 -> View + Approve Leave + Payroll

{ "_id": 5, "name": "Eve", "accessFlags": 8 } // 1000 -> Payroll

Permissions:

 Bit 0 → View Reports (1)

 Bit 1 → Edit Reports (2)

 Bit 2 → Approve Leave (4)

 Bit 3 → Manage Payroll (8)

📝 Bitwise Employee Practice Test

Q1. Find employees who have Approve Leave permission.

[Link]({

accessFlags: { $bitsAllSet: [2] }

})

✅ Output:

{ "_id": 3, "name": "Charlie", "accessFlags": 5 },

{ "_id": 4, "name": "David", "accessFlags": 13 }

Q2. Find employees who do not have Manage Payroll rights.

[Link]({

accessFlags: { $bitsAllClear: [3] }

})

✅ Output:

{ "_id": 1, "name": "Alice", "accessFlags": 1 },

{ "_id": 2, "name": "Bob", "accessFlags": 3 },

{ "_id": 3, "name": "Charlie", "accessFlags": 5 }

]
Q3. Find employees who have either Edit Reports OR Manage Payroll.

[Link]({

accessFlags: { $bitsAnySet: [1, 3] }

})

✅ Output:

{ "_id": 2, "name": "Bob", "accessFlags": 3 },

{ "_id": 4, "name": "David", "accessFlags": 13 },

{ "_id": 5, "name": "Eve", "accessFlags": 8 }

Q4. Add a field hasEditReports in projection.

[Link]([

$project: {

name: 1,

hasEditReports: {

$eq: [{ $bitAnd: ["$accessFlags", 2] }, 2]

])

✅ Output:

{ "name": "Alice", "hasEditReports": false },

{ "name": "Bob", "hasEditReports": true },

{ "name": "Charlie", "hasEditReports": false },

{ "name": "David", "hasEditReports": false },

{ "name": "Eve", "hasEditReports": false }

]
Q5. Count how many employees have each permission.

[Link]([

$group: {

_id: null,

viewReports: {

$sum: { $cond: [{ $eq: [{ $bitAnd: ["$accessFlags", 1] }, 1] }, 1, 0] }

},

editReports: {

$sum: { $cond: [{ $eq: [{ $bitAnd: ["$accessFlags", 2] }, 2] }, 1, 0] }

},

approveLeave: {

$sum: { $cond: [{ $eq: [{ $bitAnd: ["$accessFlags", 4] }, 4] }, 1, 0] }

},

managePayroll: {

$sum: { $cond: [{ $eq: [{ $bitAnd: ["$accessFlags", 8] }, 8] }, 1, 0] }

])

✅ Output:

"viewReports": 3,

"editReports": 1,

"approveLeave": 2,

"managePayroll": 2

]
Q6. Find employees with only one permission.

[Link]({

accessFlags: { $in: [1, 2, 4, 8] }

})

✅ Output:

{ "_id": 1, "name": "Alice", "accessFlags": 1 },

{ "_id": 5, "name": "Eve", "accessFlags": 8 }

Q7. Show employees with a field permissionCount = number of permissions they have.

[Link]([

$project: {

name: 1,

accessFlags: 1,

permissionCount: {

$add: [

{ $cond: [{ $eq: [{ $bitAnd: ["$accessFlags", 1] }, 1] }, 1, 0] },

{ $cond: [{ $eq: [{ $bitAnd: ["$accessFlags", 2] }, 2] }, 1, 0] },

{ $cond: [{ $eq: [{ $bitAnd: ["$accessFlags", 4] }, 4] }, 1, 0] },

{ $cond: [{ $eq: [{ $bitAnd: ["$accessFlags", 8] }, 8] }, 1, 0] }

])

✅ Output:

{ "name": "Alice", "accessFlags": 1, "permissionCount": 1 },

{ "name": "Bob", "accessFlags": 3, "permissionCount": 2 },


{ "name": "Charlie", "accessFlags": 5, "permissionCount": 2 },

{ "name": "David", "accessFlags": 13, "permissionCount": 3 },

{ "name": "Eve", "accessFlags": 8, "permissionCount": 1 }

Q8. Find the employee(s) with the maximum number of permissions.

[Link]([

$project: {

name: 1,

permissionCount: {

$add: [

{ $cond: [{ $eq: [{ $bitAnd: ["$accessFlags", 1] }, 1] }, 1, 0] },

{ $cond: [{ $eq: [{ $bitAnd: ["$accessFlags", 2] }, 2] }, 1, 0] },

{ $cond: [{ $eq: [{ $bitAnd: ["$accessFlags", 4] }, 4] }, 1, 0] },

{ $cond: [{ $eq: [{ $bitAnd: ["$accessFlags", 8] }, 8] }, 1, 0] }

},

{ $sort: { permissionCount: -1 } },

{ $limit: 1 }

])

✅ Output:

{ "name": "David", "permissionCount": 3 }

Q9. Get combined permissions across all employees.

[Link]([

{
$group: {

_id: null,

allPermissions: { $bitOr: ["$accessFlags"] }

])

✅ Output:

{ "_id": null, "allPermissions": 15 }

👉 15 = 1111 (binary) → All 4 permissions are used in the company.

Q10. Find employees who are missing at least one of (View + Edit Reports).

[Link]({

accessFlags: { $bitsAnyClear: [0, 1] }

})

✅ Output:

{ "_id": 1, "name": "Alice", "accessFlags": 1 },

{ "_id": 3, "name": "Charlie", "accessFlags": 5 },

{ "_id": 4, "name": "David", "accessFlags": 13 },

{ "_id": 5, "name": "Eve", "accessFlags": 8 }

✅ That’s a 10-question test set mixing:

 $bitsAllSet, $bitsAllClear, $bitsAnySet, $bitsAnyClear

 Aggregation with $bitAnd, $bitOr

 Counting permissions

 Finding max/min
Great question 🚀 Let’s carefully break down this query:

[Link]({

accessFlags: { $in: [1, 2, 4, 8] }

})

🔎 Step 1: $in operator

 $in: [1, 2, 4, 8] means:


Match documents where accessFlags is equal to any one of the values in the array.

So here, we are looking for employees whose accessFlags is either 1, 2, 4, or 8.

🔎 Step 2: Why these numbers?

Remember our permission bits:

Bit 0 → View Reports =1

Bit 1 → Edit Reports =2

Bit 2 → Approve Leave =4

Bit 3 → Manage Payroll = 8

So:

 1 → only View permission (0001)

 2 → only Edit permission (0010)

 4 → only Approve Leave (0100)

 8 → only Payroll (1000)

🔎 Step 3: Dataset Example

Suppose our dataset:

{ "name": "Alice", "accessFlags": 1 },

{ "name": "Bob", "accessFlags": 3 }, // View + Edit

{ "name": "Charlie", "accessFlags": 4 },

{ "name": "David", "accessFlags": 13 }, // View + Leave + Payroll

{ "name": "Eve", "accessFlags": 8 }

]
🔎 Step 4: Apply Condition

The query matches only employees whose accessFlags is exactly 1, 2, 4, or 8.

✅ Alice → 1 → match
❌ Bob → 3 → not in list
✅ Charlie → 4 → match
❌ David → 13 → not in list
✅ Eve → 8 → match

✅ Query Result

{ "name": "Alice", "accessFlags": 1 },

{ "name": "Charlie", "accessFlags": 4 },

{ "name": "Eve", "accessFlags": 8 }

👉 In simple words:
This query finds employees who have exactly one permission (only one bit set), because 1, 2, 4, 8
are powers of 2.

Perfect 👍 Let’s extend the idea.

Your query:

[Link]({

accessFlags: { $in: [1, 2, 4, 8] }

})

✅ Finds employees whose accessFlags is exactly 1, 2, 4, or 8 → i.e., they have only one permission.

🔄 Case 2: Employees who have at least one of those permissions

We don’t want “exact match” now, but rather anyone who has those bits set.
For that, we use bitwise operators:

[Link]({

accessFlags: { $bitsAnySet: [0, 1, 2, 3] }

})
📖 Explanation

 $bitsAnySet: [0,1,2,3] → Check if any of bits 0,1,2,3 are set.

 That means:

o If an employee has View (1) OR Edit (2) OR Approve Leave (4) OR Payroll (8) → they
will match.

 Basically, it finds all employees who have at least one permission.

🧮 Dataset Example

{ "name": "Alice", "accessFlags": 1 }, // View

{ "name": "Bob", "accessFlags": 3 }, // View + Edit

{ "name": "Charlie", "accessFlags": 4 }, // Approve Leave

{ "name": "David", "accessFlags": 13 }, // View + Leave + Payroll

{ "name": "Eve", "accessFlags": 8 }, // Payroll

{ "name": "Frank", "accessFlags": 0 } // No permission

✅ Matches: Alice, Bob, Charlie, David, Eve


❌ Does not match: Frank (0 = no bits set)

⚡ Difference Recap

 $in: [1, 2, 4, 8] → Only employees with exactly one permission.

 $bitsAnySet: [0,1,2,3] → Employees with any permission (one or many).

Common questions

Powered by AI

A MongoDB query using the $nor operator for employees not in the IT department nor with salaries above 50,000 would return employees who simultaneously do not belong to IT and do not have salaries greater than 50,000. This would result in employees such as Alice, Charlie, and Eva, as they meet the 'not' conditions for both department and salary criteria .

To appear in a result set using the $and logical operator with the $gt comparison, an employee must meet all specified conditions simultaneously. For example, to find employees in the IT department with a salary greater than 60,000, each employee must be in the IT department and also earn more than 60,000 .

Bitwise operations in MongoDB are highly effective for permission management as they allow for efficient handling of complex permission sets through flag combinations. For instance, each permission can be represented by a specific bit, and combinations of these can indicate multiple permissions. A scenario where this is useful is managing user access levels where individual bits represent different access rights. By reviewing these bits using operations like $bitAnd, an application can swiftly determine if a user has specific permissions without querying multiple fields .

To identify employees who lack the 'Manage Payroll' permission, you can use a query evaluating the accessFlags for the bit correctly set for 'Manage Payroll', which is a binary value of 8. Those who do not match this specific bit value do not have the permission. For example, `accessFlags: { $bitsAllClear: [3] }` checks employees who do not have 'Manage Payroll,' as this permission corresponds to bit 3 or value 8 .

To find employees whose salaries are perfectly divisible by 10,000, you use the $mod operator in MongoDB. The query would be: `{ "salary": { $mod: [10000, 0] } }`. This checks if the remainder of dividing the salary by 10,000 is zero, indicating divisibility .

$expr is advantageous over $where in MongoDB as it utilizes aggregation expressions, making operations faster and safer since it doesn’t execute raw JavaScript, unlike $where. For example, using $expr to find employees whose salary is greater than their age multiplied by 2000 would be expressed as: `{ $expr: { $gt: ["$salary", { $multiply: ["$age", 2000] }] } }`. This ensures efficient evaluation over large datasets without the security risks associated with JavaScript .

To find employees whose names start with 'A', you use the $regex operator in MongoDB. The pattern would be `{ "name": { $regex: /^A/, $options: "i" } }`, where `^A` specifies names beginning with 'A' and the `i` option makes it case-insensitive .

Using the MongoDB aggregation pipeline, combined permissions can be calculated by grouping all employee documents and applying the $bitOr operation across the accessFlags. This aggregates the set of permissions across all employees. A "combinedPermissions" result of 15 indicates that all possible permissions (in this case, View Reports, Edit Reports, Approve Leave, Manage Payroll) are utilized across the workforce as 15 in binary (1111) represents all bits being set .

Bitwise aggregation can identify an employee with only a single type of permission by matching their accessFlags with a power of two, indicative of a single bit being set. For example, using $bitAnd in combination with logarithmic calculations, one can verify if an accessFlag corresponds exactly to a power of two. For instance, Alice with accessFlags: 1 (binary 0001), can be identified as having only 'View Reports,' as it's the only bit active .

You can determine which employees have both 'Excel' and 'Recruitment' skills by using the $all array operator. The query checks if all specified elements are present in the 'skills' array of each document. For example: `{ "skills": { $all: ["Excel", "Recruitment"] } }` will return employees like Alice who possess both these skills .

You might also like