Question # 1
Query Arrays in MongoDB:
In MongoDB, arrays are commonly used to store multiple values in a single field. MongoDB
provides powerful operators to query arrays, such as $elemMatch, $all, $size, and positional
operators. Below are examples of querying arrays in MongoDB with explanations and expected
outputs.
1. Querying Documents That Contain a Specific Value in an Array
If you want to find documents where an array field contains a specific value:
Query: Find documents where the tags array contains the value "technology".
db.articles.find({ tags: "technology" });
Explanation: MongoDB automatically searches for the value "technology" in the array field
tags.
Output:
{ "_id": 1, "title": "Tech News", "tags": ["technology", "news"] },
{ "_id": 3, "title": "AI Trends", "tags": ["technology", "AI"] }
2. Match Documents Where an Array Contains All Specified Values
If you want to check if an array contains all of several specified values:
Query: Find documents where the tags array contains both "technology" and "AI".
db.articles.find({ tags: { $all: ["technology", "AI"] } });
Explanation: The $all operator matches arrays that contain all the specified elements, in any
order.
Output:
[
{ "_id": 3, "title": "AI Trends", "tags": ["technology", "AI"] }
3. Querying Documents Where an Array Contains an Element Matching Specific
Conditions
If you want to query based on conditions for elements in the array:
Query: Find documents where the ratings array has at least one element greater than 4.
db.products.find({ ratings: { $gt: 4 } });
Explanation: The $gt operator checks if any element in the ratings array is greater than 4.
Output:
{ "_id": 1, "name": "Product A", "ratings": [3, 5, 4] },
{ "_id": 2, "name": "Product B", "ratings": [5, 5] }
4. Querying Using $elemMatch for Complex Array Elements
If you want to find documents where an array contains an element matching multiple conditions:
Query: Find documents where the grades array contains an object with "score" greater than 80
and "subject" equal to "math".
db.students.find({
grades: { $elemMatch: { score: { $gt: 80 }, subject: "math" } }
});
Explanation: The $elemMatch operator matches array elements that satisfy all the specified
conditions.
Output:
[
{ "_id": 1, "name": "Alice", "grades": [{ "subject": "math", "score": 85 }, { "subject": "science",
"score": 90 }] },
{ "_id": 3, "name": "Charlie", "grades": [{ "subject": "math", "score": 95 }] }
5. Querying the Size of an Array
If you want to match documents based on the size of an array:
Query: Find documents where the tags array has exactly 3 elements.
db.articles.find({ tags: { $size: 3 } });
Explanation: The $size operator matches documents where the array field contains the specified
number of elements.
Output:
{ "_id": 2, "title": "Web Development", "tags": ["web", "development", "programming"] }
6. Updating Specific Elements in an Array
You can also update specific elements in an array using the positional operator ($):
Query: Update the first occurrence of a grade with a "subject" of "math" to have a "score" of 95.
db.students.updateOne(
{ "grades.subject": "math" },
{ $set: { "grades.$.score": 95 } }
);
Explanation: The $ operator refers to the first matching element in the array.
Result After Update:
{ "_id": 1, "name": "Alice", "grades": [{ "subject": "math", "score": 95 }, { "subject": "science",
"score": 90 }] }
Question # 2
Transactions in MongoDB
Transactions in MongoDB allow multiple operations to be executed as a single, atomic unit. This
ensures that all operations in the transaction succeed or none of them take effect, maintaining
ACID (Atomicity, Consistency, Isolation, Durability) principles.
Features of Transactions in MongoDB
1. Atomicity: Either all operations in the transaction succeed, or none of them are applied.
2. Multi-Document: Transactions allow operations across multiple documents and
collections.
3. Multi-Statements: You can execute multiple read and write operations within a single
transaction.
4. Durability: Changes are durable once the transaction is committed.
Steps to Use Transactions in MongoDB
1. Starting a Session
A transaction is always tied to a session. You must start a session before using a transaction.
2. Starting a Transaction
Use the startTransaction() method on the session object to initiate a transaction.
3. Performing Operations
You can perform multiple read and write operations within the transaction.
4. Committing or Aborting
Use commitTransaction() to apply all changes.
Use abortTransaction() to discard changes.
MongoDB Transactions Example
Scenario:
We have a database named bank with a collection accounts. Each document in the accounts
collection represents a bank account with fields account_number and balance.
We want to:
1. Deduct $100 from Account 12345.
2. Add $100 to Account 67890.
3. Ensure both operations succeed together or fail together.
Sample Data
db.accounts.insertMany([
{ account_number: 12345, balance: 500 },
{ account_number: 67890, balance: 300 }
]);
Transaction Query
// Start a session
const session = db.getMongo().startSession();
session.startTransaction(); // Start the transaction
try {
const accounts = session.getDatabase("bank").accounts;
// Deduct $100 from account 12345
accounts.updateOne(
{ account_number: 12345 },
{ $inc: { balance: -100 } },
{ session }
);
// Add $100 to account 67890
accounts.updateOne(
{ account_number: 67890 },
{ $inc: { balance: 100 } },
{ session }
);
// Commit the transaction
session.commitTransaction();
print("Transaction committed.");
} catch (error) {
// Abort the transaction in case of an error
session.abortTransaction();
print("Transaction aborted due to an error: " + error);
} finally {
session.endSession(); // End the session
Output
Before the Transaction:
db.accounts.find().pretty();
{ "_id": ObjectId("64b1234567890a"), "account_number": 12345, "balance": 500 },
{ "_id": ObjectId("64b1234567890b"), "account_number": 67890, "balance": 300 }
After the Transaction (if successful):
db.accounts.find().pretty();
{ "_id": ObjectId("64b1234567890a"), "account_number": 12345, "balance": 400 },
{ "_id": ObjectId("64b1234567890b"), "account_number": 67890, "balance": 400 }
If the Transaction Fails (e.g., due to an error): No changes are made, and the data remains as
it was before the transaction:
{ "_id": ObjectId("64b1234567890a"), "account_number": 12345, "balance": 500 },
{ "_id": ObjectId("64b1234567890b"), "account_number": 67890, "balance": 300 }
Transaction Logs:
If successful:
"Transaction committed."
If failed:
"Transaction aborted due to an error: ..."
Explanation of the Query
1. Start a session: The startSession() function initiates a session for the transaction.
2. Start a transaction: startTransaction() begins a transaction within the session.
3. Perform operations:
$inc is used to modify the balance field.
Operations are performed using the session object.
4. Commit or abort:
commitTransaction() ensures all changes are applied if no errors occur.
abortTransaction() rolls back the changes in case of errors.
5. End the session: Finally, the session is closed.