MongoDB Movie Rating Database Queries

Database Schema: Practice MongoDB queries on a Telugu movie rating database with document operations, aggregation, and indexing.
S.No Movie Name Year Actor Director Rating Review
1 Baahubali: The Beginning 2015 Prabhas S.S. Rajamouli 4.8 Epic visual spectacle that revolutionized Indian cinema
2 Baahubali 2: The Conclusion 2017 Prabhas S.S. Rajamouli 4.9 Grand conclusion to the epic saga with amazing climax
3 RRR 2022 N.T. Rama Rao Jr. S.S. Rajamouli 4.9 Oscar-winning masterpiece with breathtaking action sequences
4 Pushpa: The Rise 2021 Allu Arjun Sukumar 4.5 Mass entertainer with Allu Arjun's iconic performance
5 Ala Vaikunthapurramuloo 2020 Allu Arjun Trivikram Srinivas 4.3 Perfect blend of entertainment and emotions
6 Arjun Reddy 2017 Vijay Deverakonda Sandeep Reddy Vanga 4.2 Bold and intense romantic drama
7 Jersey 2019 Nani Gowtam Tinnanuri 4.6 Heartwarming sports drama with brilliant performances
8 Sita Ramam 2022 Dulquer Salmaan Hanu Raghavapudi 4.7 Beautiful period love story with soulful music
9 Eega 2012 Nani S.S. Rajamouli 4.4 Innovative revenge story with amazing visual effects
10 Majili 2019 Nani Shiva Nirvana 4.1 Emotional love story with realistic performances

Collection Creation MongoDB

// Create collection with schema validation
db.createCollection("movie_ratings", {
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: ["moviename", "released_year", "actor", "director", "rating"],
      properties: {
        moviename: {
          bsonType: "string",
          description: "must be a string and is required"
        },
        released_year: {
          bsonType: "int",
          minimum: 1900,
          maximum: new Date().getFullYear(),
          description: "must be an integer between 1900 and current year"
        },
        actor: {
          bsonType: "string",
          description: "must be a string and is required"
        },
        director: {
          bsonType: "string",
          description: "must be a string and is required"
        },
        rating: {
          bsonType: "double",
          minimum: 0.5,
          maximum: 5.0,
          description: "must be a double between 0.5 and 5.0"
        },
        review: {
          bsonType: "string",
          description: "must be a string if the field exists"
        },
        last_updated: {
          bsonType: "date",
          description: "must be a date if the field exists"
        }
      }
    }
  }
});

// Insert sample documents
db.movie_ratings.insertMany([
  {
    moviename: "Baahubali: The Beginning",
    released_year: 2015,
    actor: "Prabhas",
    director: "S.S. Rajamouli",
    rating: 4.8,
    review: "Epic visual spectacle that revolutionized Indian cinema",
    last_updated: new Date()
  },
  {
    moviename: "Baahubali 2: The Conclusion",
    released_year: 2017,
    actor: "Prabhas",
    director: "S.S. Rajamouli",
    rating: 4.9,
    review: "Grand conclusion to the epic saga with amazing climax",
    last_updated: new Date()
  },
  {
    moviename: "RRR",
    released_year: 2022,
    actor: "N.T. Rama Rao Jr.",
    director: "S.S. Rajamouli",
    rating: 4.9,
    review: "Oscar-winning masterpiece with breathtaking action sequences",
    last_updated: new Date()
  },
  {
    moviename: "Pushpa: The Rise",
    released_year: 2021,
    actor: "Allu Arjun",
    director: "Sukumar",
    rating: 4.5,
    review: "Mass entertainer with Allu Arjun's iconic performance",
    last_updated: new Date()
  },
  {
    moviename: "Ala Vaikunthapurramuloo",
    released_year: 2020,
    actor: "Allu Arjun",
    director: "Trivikram Srinivas",
    rating: 4.3,
    review: "Perfect blend of entertainment and emotions",
    last_updated: new Date()
  },
  {
    moviename: "Arjun Reddy",
    released_year: 2017,
    actor: "Vijay Deverakonda",
    director: "Sandeep Reddy Vanga",
    rating: 4.2,
    review: "Bold and intense romantic drama",
    last_updated: new Date()
  },
  {
    moviename: "Jersey",
    released_year: 2019,
    actor: "Nani",
    director: "Gowtam Tinnanuri",
    rating: 4.6,
    review: "Heartwarming sports drama with brilliant performances",
    last_updated: new Date()
  },
  {
    moviename: "Sita Ramam",
    released_year: 2022,
    actor: "Dulquer Salmaan",
    director: "Hanu Raghavapudi",
    rating: 4.7,
    review: "Beautiful period love story with soulful music",
    last_updated: new Date()
  },
  {
    moviename: "Eega",
    released_year: 2012,
    actor: "Nani",
    director: "S.S. Rajamouli",
    rating: 4.4,
    review: "Innovative revenge story with amazing visual effects",
    last_updated: new Date()
  },
  {
    moviename: "Majili",
    released_year: 2019,
    actor: "Nani",
    director: "Shiva Nirvana",
    rating: 4.1,
    review: "Emotional love story with realistic performances",
    last_updated: new Date()
  }
]);

Interactive FIND Queries

Hover over each query to see the MongoDB statement and expected results.

1. Display all movies with their release year and rating, sorted alphabetically by movie name

db.movie_ratings.find(
  {},
  { moviename: 1, released_year: 1, rating: 1, _id: 0 }
).sort({ moviename: 1 });

2. Show the 5 movies with the highest ratings in descending order

db.movie_ratings.find(
  {},
  { moviename: 1, rating: 1, _id: 0 }
).sort({ rating: -1 }).limit(5);

3. List all movies directed by S.S. Rajamouli in chronological order

db.movie_ratings.find(
  { director: /Rajamouli/i },
  { moviename: 1, released_year: 1, _id: 0 }
).sort({ released_year: 1 });

4. Display Allu Arjun's movies sorted by rating (highest first)

db.movie_ratings.find(
  { actor: "Allu Arjun" },
  { moviename: 1, released_year: 1, rating: 1, _id: 0 }
).sort({ rating: -1 });

5. Show movies released in the most recent 5 years

const currentYear = new Date().getFullYear();
db.movie_ratings.find(
  { released_year: { $gte: currentYear - 5 } },
  { moviename: 1, released_year: 1, _id: 0 }
).sort({ released_year: -1 });

6. Find movies where the review contains the word "performance"

db.movie_ratings.find(
  { review: /performance/i },
  { moviename: 1, review: 1, _id: 0 }
);

7. Find movies with rating between 4.5 and 5.0

db.movie_ratings.find(
  { rating: { $gte: 4.5, $lte: 5.0 } },
  { moviename: 1, rating: 1, _id: 0 }
).sort({ rating: -1 });

8. Find movies with lengthy reviews (more than 50 characters)

db.movie_ratings.find({
  $expr: { $gt: [{ $strLenCP: "$review" }, 50] }
}, {
  moviename: 1,
  review_length: { $strLenCP: "$review" },
  _id: 0
}).sort({ review_length: -1 });

9. Find movies released on leap years

db.movie_ratings.find({
  $expr: {
    $or: [
      { $and: [
          { $eq: [{ $mod: ["$released_year", 4] }, 0] },
          { $ne: [{ $mod: ["$released_year", 100] }, 0] }
      ]},
      { $eq: [{ $mod: ["$released_year", 400] }, 0] }
    ]
  }
}, {
  moviename: 1,
  released_year: 1,
  _id: 0
});

10. Find movies with specific actors using $in operator

db.movie_ratings.find({
  actor: { $in: ["Prabhas", "Allu Arjun", "Nani"] }
}, {
  moviename: 1,
  actor: 1,
  rating: 1,
  _id: 0
}).sort({ rating: -1 });

UPDATE Operations

Hover over each query to see the MongoDB statement and expected results.

1. Update Rating for a Specific Movie

db.movie_ratings.updateOne(
  { moviename: "Majili" },
  { $set: { rating: 4.7 } }
);

Updates the rating of 'Majili' to 4.7

2. Update Review Text

db.movie_ratings.updateOne(
  { moviename: "Baahubali: The Beginning" },
  { $set: { review: "Epic masterpiece that changed Indian cinema forever" } }
);

Modifies the review text for Baahubali: The Beginning

3. Update Multiple Fields (Rating + Review)

db.movie_ratings.updateOne(
  { moviename: "RRR" },
  { $set: { 
      rating: 4.8,
      review: "Even better on second viewing - true classic" 
    } 
  }
);

Updates both rating and review for RRR simultaneously

4. Conditional Update (Only if Current Rating is Lower)

db.movie_ratings.updateOne(
  { 
    moviename: "Arjun Reddy",
    rating: { $lt: 4.6 }
  },
  { $set: { rating: 4.6 } }
);

Only updates if current rating is below 4.6

5. Update Director Name for Multiple Movies

db.movie_ratings.updateMany(
  { director: /Rajamouli/i },
  { $set: { director: "S.S. Rajamouli" } }
);

Standardizes director name format for all Rajamouli movies

6. Update Based on Release Year

db.movie_ratings.updateMany(
  { 
    released_year: 2022,
    rating: { $lte: 4.9 }
  },
  { $inc: { rating: 0.1 } }
);

Gives a small rating boost to all 2022 releases

7. Update Actor Name (Alias Correction)

db.movie_ratings.updateMany(
  { actor: "N.T. Rama Rao Jr." },
  { $set: { actor: "Jr. NTR" } }
);

Changes actor name to more common alias

8. Increment All Ratings by 0.1 (Max 5.0)

db.movie_ratings.updateMany(
  {},
  [
    { $set: { 
        rating: { 
          $min: [ { $add: ["$rating", 0.1] }, 5.0 ] 
        } 
      } 
    }
  ]
);

Gives all movies a small rating boost without exceeding 5.0

9. Add a New Field to Documents

db.movie_ratings.updateMany(
  {},
  { $set: { language: "Telugu" } }
);

Adds a language field to all documents with value "Telugu"

10. Update with Aggregation Pipeline

db.movie_ratings.updateMany(
  {},
  [
    {
      $set: {
        rating: {
          $cond: [
            { $eq: ["$director", "S.S. Rajamouli"] },
            { $min: [{ $add: ["$rating", 0.2] }, 5.0] },
            { $cond: [
                { $gte: ["$released_year", 2020] },
                { $min: [{ $add: ["$rating", 0.1] }, 5.0] },
                "$rating"
              ]
            }
          ]
        }
      }
    }
  ]
);

Gives Rajamouli movies extra boost, recent movies small boost

Aggregation Pipeline Queries

Hover over each query to see the MongoDB statement and expected results.

1. Calculate average ratings for actors with at least 2 movies

db.movie_ratings.aggregate([
  {
    $group: {
      _id: "$actor",
      avg_rating: { $avg: "$rating" },
      movie_count: { $sum: 1 }
    }
  },
  { $match: { movie_count: { $gte: 2 } } },
  { $sort: { avg_rating: -1 } }
]);

2. Provide statistics about movies grouped by release year

db.movie_ratings.aggregate([
  {
    $group: {
      _id: "$released_year",
      movie_count: { $sum: 1 },
      avg_rating: { $avg: "$rating" },
      max_rating: { $max: "$rating" }
    }
  },
  { $sort: { _id: -1 } }
]);

3. Categorize movies into rating ranges and count them

db.movie_ratings.aggregate([
  {
    $bucket: {
      groupBy: "$rating",
      boundaries: [0, 3, 4, 5],
      default: "Other",
      output: {
        count: { $sum: 1 },
        movies: { $push: "$moviename" }
      }
    }
  }
]);

4. Group movies by actor with stats

db.movie_ratings.aggregate([
  {
    $group: {
      _id: "$actor",
      movies: { $push: "$moviename" },
      movie_count: { $sum: 1 },
      avg_rating: { $avg: "$rating" },
      min_rating: { $min: "$rating" },
      max_rating: { $max: "$rating" }
    }
  },
  { $sort: { movie_count: -1, avg_rating: -1 } }
]);

5. Count reviews containing "performance"

db.movie_ratings.aggregate([
  {
    $match: {
      review: /performance/i
    }
  },
  {
    $count: "performance_reviews"
  }
]);

6. Find longest and shortest movie names

db.movie_ratings.aggregate([
  {
    $project: {
      moviename: 1,
      name_length: { $strLenCP: "$moviename" }
    }
  },
  { $sort: { name_length: -1 } },
  { $limit: 1 },
  {
    $unionWith: {
      coll: "movie_ratings",
      pipeline: [
        {
          $project: {
            moviename: 1,
            name_length: { $strLenCP: "$moviename" }
          }
        },
        { $sort: { name_length: 1 } },
        { $limit: 1 }
      ]
    }
  }
]);

7. Group movies by release quarter (Q1-Q4)

db.movie_ratings.aggregate([
  {
    $project: {
      moviename: 1,
      quarter: {
        $concat: [
          "Q",
          {
            $toString: {
              $ceil: {
                $divide: [
                  {
                    $mod: [
                      { $add: ["$released_year", 0] },
                      12
                    ]
                  },
                  3
                ]
              }
            }
          }
        ]
      }
    }
  },
  {
    $group: {
      _id: "$quarter",
      movie_count: { $sum: 1 }
    }
  },
  { $sort: { _id: 1 } }
]);

8. Extract the last word from each review

db.movie_ratings.aggregate([
  {
    $project: {
      moviename: 1,
      last_word: {
        $arrayElemAt: [
          { $split: ["$review", " "] },
          -1
        ]
      }
    }
  }
]);

9. Find movies where review contains exactly 50 characters

db.movie_ratings.aggregate([
  {
    $project: {
      moviename: 1,
      review: 1,
      review_length: { $strLenCP: "$review" }
    }
  },
  {
    $match: {
      review_length: 50
    }
  }
]);

10. Calculate average rating by year with $facet

db.movie_ratings.aggregate([
  {
    $facet: {
      "by_year": [
        {
          $group: {
            _id: "$released_year",
            avg_rating: { $avg: "$rating" }
          }
        },
        { $sort: { _id: 1 } }
      ],
      "overall": [
        {
          $group: {
            _id: null,
            avg_rating: { $avg: "$rating" }
          }
        }
      ]
    }
  }
]);

DELETE Operations

Hover over each query to see the MongoDB statement and expected results.

1. Delete Single Movie by Name

db.movie_ratings.deleteOne(
  { moviename: "Majili" }
);

Removes the specific movie 'Majili' from the collection

2. Delete Movies by Release Year (Older Films)

db.movie_ratings.deleteMany(
  { released_year: { $lt: 2015 } }
);

Deletes all movies released before 2015

3. Delete Low-Rated Movies

db.movie_ratings.deleteMany(
  { rating: { $lt: 4.0 } }
);

Removes all movies with ratings below 4.0 stars

4. Delete Using Multiple Conditions

db.movie_ratings.deleteMany(
  { actor: "Nani", rating: { $lt: 4.3 } }
);

Deletes Nani's movies with ratings below 4.3

5. Delete All Movies by a Director

db.movie_ratings.deleteMany(
  { director: "Sandeep Reddy Vanga" }
);

Removes all movies directed by Sandeep Reddy Vanga

6. Delete Using Pattern Matching

db.movie_ratings.deleteMany(
  { moviename: { $regex: /test|temp/i } }
);

Removes any test or temporary entries in the database

7. Delete Duplicate Movies (Keeping Highest Rated)

// First identify duplicates
const duplicates = db.movie_ratings.aggregate([
  {
    $group: {
      _id: "$moviename",
      count: { $sum: 1 },
      ids: { $push: "$_id" },
      maxRating: { $max: "$rating" }
    }
  },
  { $match: { count: { $gt: 1 } } }
]);

// Then delete duplicates keeping highest rated
duplicates.forEach(function(doc) {
  db.movie_ratings.deleteMany({
    _id: { $in: doc.ids },
    rating: { $lt: doc.maxRating }
  });
});

Removes duplicate movie entries, keeping only the highest rated version

8. Delete All Data (Empty Collection)

db.movie_ratings.deleteMany({});

Removes all documents from the collection while keeping the structure

9. Delete Collection

db.movie_ratings.drop();

Completely removes the collection and its indexes

Indexes in MongoDB

Hover over each query to see the MongoDB statement and expected results.

1. Create a Basic Index on Movie Name

db.movie_ratings.createIndex(
  { moviename: 1 }
);

Creates an ascending index on the moviename field

2. Create Compound Index on Director and Year

db.movie_ratings.createIndex(
  { director: 1, released_year: -1 }
);

Creates an index on director (ascending) and year (descending)

3. Create Unique Index on Movie+Year Combination

db.movie_ratings.createIndex(
  { moviename: 1, released_year: 1 },
  { unique: true }
);

Ensures no duplicate movie entries for the same year

4. Show All Indexes on the Collection

db.movie_ratings.getIndexes();

Displays all indexes defined on the movie_ratings collection

5. Drop an Index

db.movie_ratings.dropIndex(
  "moviename_1"
);

Removes the moviename index from the collection

6. Create Text Index on Review Column

db.movie_ratings.createIndex(
  { review: "text" }
);

Creates a text index for full-text search on reviews

7. Explain Query with Index Usage

db.movie_ratings.find(
  { director: "S.S. Rajamouli", released_year: { $gt: 2015 } }
).explain("executionStats");

Shows query execution plan and index usage

8. Use Text Search with Index

db.movie_ratings.find(
  { $text: { $search: "performance" } },
  { moviename: 1, review: 1 }
);

Performs optimized text search using the text index

9. Create Partial Index

db.movie_ratings.createIndex(
  { rating: 1 },
  { partialFilterExpression: { rating: { $gt: 4.0 } } }
);

Creates an index only for documents with rating > 4.0

10. Create TTL Index

db.movie_ratings.createIndex(
  { last_updated: 1 },
  { expireAfterSeconds: 31536000 } // 1 year
);

Automatically removes documents older than 1 year

Indexing Best Practices

  • Index fields frequently used in queries, sorts, and aggregations
  • Use compound indexes for queries on multiple fields
  • Consider index selectivity - more selective fields first
  • Use explain() to analyze query performance
  • Monitor index usage with $indexStats
  • Consider partial indexes for large collections with specific query patterns

Date Operations

Hover over each query to see the MongoDB statement and expected results.

1. Display years passed since each movie was released

db.movie_ratings.aggregate([
  {
    $project: {
      moviename: 1,
      released_year: 1,
      years_since_release: {
        $subtract: [
          { $year: new Date() },
          "$released_year"
        ]
      }
    }
  }
]);

2. Find movies released in the last 5 years

const currentYear = new Date().getFullYear();
db.movie_ratings.find(
  { released_year: { $gte: currentYear - 5 } },
  { moviename: 1, released_year: 1 }
).sort({ released_year: -1 });

3. Group movies by release year and count

db.movie_ratings.aggregate([
  {
    $group: {
      _id: "$released_year",
      movie_count: { $sum: 1 }
    }
  },
  { $sort: { movie_count: -1 } }
]);

4. Find movies released on leap years

db.movie_ratings.find({
  $expr: {
    $or: [
      { $and: [
          { $eq: [{ $mod: ["$released_year", 4] }, 0] },
          { $ne: [{ $mod: ["$released_year", 100] }, 0] }
      ]},
      { $eq: [{ $mod: ["$released_year", 400] }, 0] }
    ]
  }
});

5. Calculate days between Baahubali 1 and 2 releases

db.movie_ratings.aggregate([
  {
    $match: {
      moviename: { $in: ["Baahubali: The Beginning", "Baahubali 2: The Conclusion"] }
    }
  },
  {
    $group: {
      _id: null,
      dates: { $push: "$released_year" }
    }
  },
  {
    $project: {
      days_between: {
        $abs: {
          $subtract: [
            { $arrayElemAt: ["$dates", 0] },
            { $arrayElemAt: ["$dates", 1] }
          ]
        }
      }
    }
  }
]);

6. Find movies updated in the last 7 days

const sevenDaysAgo = new Date();
sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);

db.movie_ratings.find(
  { last_updated: { $gte: sevenDaysAgo } }
);

7. Group movies by month of last update

db.movie_ratings.aggregate([
  {
    $project: {
      moviename: 1,
      update_month: { $month: "$last_updated" }
    }
  },
  {
    $group: {
      _id: "$update_month",
      movies: { $push: "$moviename" }
    }
  }
]);

8. Find movies updated today

const today = new Date();
today.setHours(0, 0, 0, 0);

db.movie_ratings.find(
  { last_updated: { $gte: today } }
);

Sorting and Limiting

Hover over each query to see the MongoDB statement and expected results.

1. Sort movies by rating (highest first)

db.movie_ratings.find(
  {},
  { moviename: 1, rating: 1, _id: 0 }
).sort({ rating: -1 });

2. Sort movies by release year (oldest first)

db.movie_ratings.find(
  {},
  { moviename: 1, released_year: 1, _id: 0 }
).sort({ released_year: 1 });

3. Sort by multiple fields (director then rating)

db.movie_ratings.find().sort(
  { director: 1, rating: -1 }
);

4. Limit results to top 5 rated movies

db.movie_ratings.find()
  .sort({ rating: -1 })
  .limit(5);

5. Skip first 2 results and limit to next 3

db.movie_ratings.find()
  .sort({ moviename: 1 })
  .skip(2)
  .limit(3);

6. Sort by text score (with text search)

db.movie_ratings.find(
  { $text: { $search: "epic performance" } },
  { score: { $meta: "textScore" } }
).sort({ score: { $meta: "textScore" } });

7. Sort by calculated field (review length)

db.movie_ratings.aggregate([
  {
    $addFields: {
      review_length: { $strLenCP: "$review" }
    }
  },
  { $sort: { review_length: -1 } },
  { $limit: 3 }
]);

8. Random sampling of documents

db.movie_ratings.aggregate([
  { $sample: { size: 3 } }
]);

Schema Validation

Hover over each query to see the MongoDB statement and expected results.

1. View current validation rules

db.getCollectionInfos({ name: "movie_ratings" });

2. Add validation to existing collection

db.runCommand({
  collMod: "movie_ratings",
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: ["moviename", "released_year", "actor", "director", "rating"],
      properties: {
        moviename: { bsonType: "string" },
        released_year: { bsonType: "int", minimum: 1900, maximum: new Date().getFullYear() },
        rating: { bsonType: "double", minimum: 0.5, maximum: 5.0 }
      }
    }
  },
  validationLevel: "strict",
  validationAction: "error"
});

3. Test validation with invalid document

// Should fail (rating too high)
db.movie_ratings.insertOne({
  moviename: "Test Movie",
  released_year: 2023,
  actor: "Actor",
  director: "Director",
  rating: 5.5
});

4. Test validation with missing required field

// Should fail (missing moviename)
db.movie_ratings.insertOne({
  released_year: 2023,
  actor: "Actor",
  director: "Director",
  rating: 4.5
});

5. Add validation for OTT platform field

db.runCommand({
  collMod: "movie_ratings",
  validator: {
    $jsonSchema: {
      properties: {
        ott_platform: {
          bsonType: "string",
          enum: ["Netflix", "Prime", "Hotstar", "Zee5", "Aha", "Disney+"]
        }
      }
    }
  }
});

6. Test OTT platform validation

// Should fail (invalid platform)
db.movie_ratings.insertOne({
  moviename: "Test Movie",
  released_year: 2023,
  actor: "Actor",
  director: "Director",
  rating: 4.5,
  ott_platform: "YouTube"
});

7. Add validation for review length

db.runCommand({
  collMod: "movie_ratings",
  validator: {
    $jsonSchema: {
      properties: {
        review: {
          bsonType: "string",
          minLength: 10,
          maxLength: 500
        }
      }
    }
  }
});

8. Temporarily bypass validation

db.movie_ratings.insertOne(
  {
    moviename: "Temp Movie",
    released_year: 2023,
    actor: "Actor",
    director: "Director",
    rating: 6.0  // Invalid
  },
  { bypassDocumentValidation: true }
);

9. Query validation violations

// Find documents that don't match current schema
db.movie_ratings.find({
  $where: function() {
    return !db.movie_ratings.validate(this).valid;
  }
});

Schema Validation Best Practices

  • Use validation to ensure data consistency
  • Start with loose validation and tighten over time
  • Consider using validationLevel: "moderate" for existing collections
  • Document your schema expectations clearly
  • Test validation rules thoroughly before deployment

Transactions in MongoDB

Hover over each query to see the MongoDB statement and expected results.

1. Basic transaction example

const session = db.getMongo().startSession();
session.startTransaction();

try {
  // Update movie rating
  db.movie_ratings.updateOne(
    { moviename: "RRR" },
    { $set: { rating: 5.0 } },
    { session }
  );
  
  // Insert log entry
  db.rating_changes.insertOne({
    moviename: "RRR",
    old_rating: 4.9,
    new_rating: 5.0,
    changed_at: new Date()
  }, { session });
  
  session.commitTransaction();
} catch (error) {
  session.abortTransaction();
  throw error;
} finally {
  session.endSession();
}

2. Transaction with read operations

const session = db.getMongo().startSession();
session.startTransaction();

try {
  // Get current rating
  const movie = db.movie_ratings.findOne(
    { moviename: "Baahubali: The Beginning" },
    { session }
  );
  
  // Update based on current value
  db.movie_ratings.updateOne(
    { moviename: "Baahubali: The Beginning" },
    { $set: { rating: movie.rating + 0.1 } },
    { session }
  );
  
  session.commitTransaction();
} catch (error) {
  session.abortTransaction();
  throw error;
} finally {
  session.endSession();
}

3. Multi-document transaction

const session = db.getMongo().startSession();
session.startTransaction();

try {
  // Update multiple movies
  db.movie_ratings.updateMany(
    { director: "S.S. Rajamouli" },
    { $inc: { rating: 0.1 } },
    { session }
  );
  
  // Update director stats
  db.director_stats.updateOne(
    { name: "S.S. Rajamouli" },
    { $inc: { total_updates: 1 } },
    { session }
  );
  
  session.commitTransaction();
} catch (error) {
  session.abortTransaction();
  throw error;
} finally {
  session.endSession();
}

4. Transaction with error handling

const session = db.getMongo().startSession();

try {
  session.startTransaction({
    readConcern: { level: "snapshot" },
    writeConcern: { w: "majority" }
  });
  
  // Operations here
  
  session.commitTransaction();
} catch (error) {
  if (error.errorLabels && error.errorLabels.includes("TransientTransactionError")) {
    console.log("Transient error, retrying...");
    // Implement retry logic
  } else {
    console.log("Error in transaction:", error);
    session.abortTransaction();
  }
} finally {
  session.endSession();
}

Transaction Best Practices

  • Keep transactions short (under 1 second ideally)
  • Use retry logic for transient errors
  • Specify appropriate read and write concerns
  • Avoid operations that create collections in transactions
  • Test transaction behavior under failure conditions

Joins with $lookup

Hover over each query to see the MongoDB statement and expected results.

Note: For $lookup examples, we'll use an additional collection called movie_awards:
db.createCollection("movie_awards");

db.movie_awards.insertMany([
  {
    moviename: "Baahubali: The Beginning",
    award_name: "National Film Award",
    award_year: 2016,
    category: "Best Feature Film"
  },
  {
    moviename: "Baahubali: The Beginning",
    award_name: "Filmfare Award",
    award_year: 2016,
    category: "Best Film"
  },
  {
    moviename: "RRR",
    award_name: "Oscar",
    award_year: 2023,
    category: "Best Original Song"
  },
  {
    moviename: "RRR",
    award_name: "Golden Globe",
    award_year: 2023,
    category: "Best Foreign Language Film"
  },
  {
    moviename: "Pushpa: The Rise",
    award_name: "Filmfare Award",
    award_year: 2022,
    category: "Best Actor"
  },
  {
    moviename: "Sita Ramam",
    award_name: "National Film Award",
    award_year: 2023,
    category: "Best Music Direction"
  },
  {
    moviename: "Jersey",
    award_name: "Filmfare Award",
    award_year: 2020,
    category: "Best Actor"
  }
]);

1. Basic $lookup - Movies with Awards

db.movie_ratings.aggregate([
  {
    $lookup: {
      from: "movie_awards",
      localField: "moviename",
      foreignField: "moviename",
      as: "awards"
    }
  },
  { $match: { awards: { $ne: [] } } },
  { $sort: { "awards.award_year": -1 } }
]);

2. $lookup with $unwind - One doc per award

db.movie_ratings.aggregate([
  {
    $lookup: {
      from: "movie_awards",
      localField: "moviename",
      foreignField: "moviename",
      as: "awards"
    }
  },
  { $unwind: "$awards" },
  {
    $project: {
      moviename: 1,
      award_name: "$awards.award_name",
      award_year: "$awards.award_year"
    }
  }
]);

3. $lookup with pipeline - Filtered join

db.movie_ratings.aggregate([
  {
    $lookup: {
      from: "movie_awards",
      let: { movie_name: "$moviename" },
      pipeline: [
        {
          $match: {
            $expr: {
              $and: [
                { $eq: ["$moviename", "$$movie_name"] },
                { $gte: ["$award_year", 2020] }
              ]
            }
          }
        }
      ],
      as: "recent_awards"
    }
  }
]);

4. $lookup with $mergeObjects - Combine fields

db.movie_ratings.aggregate([
  {
    $lookup: {
      from: "movie_awards",
      localField: "moviename",
      foreignField: "moviename",
      as: "awards"
    }
  },
  {
    $replaceRoot: {
      newRoot: {
        $mergeObjects: [
          "$$ROOT",
          { award_count: { $size: "$awards" } }
        ]
      }
    }
  }
]);

5. Multiple $lookups - Movies with awards and stats

db.movie_ratings.aggregate([
  {
    $lookup: {
      from: "movie_awards",
      localField: "moviename",
      foreignField: "moviename",
      as: "awards"
    }
  },
  {
    $lookup: {
      from: "director_stats",
      localField: "director",
      foreignField: "name",
      as: "director_info"
    }
  },
  { $unwind: { path: "$director_info", preserveNullAndEmptyArrays: true } }
]);

6. $lookup with $group - Count awards per movie

db.movie_ratings.aggregate([
  {
    $lookup: {
      from: "movie_awards",
      localField: "moviename",
      foreignField: "moviename",
      as: "awards"
    }
  },
  {
    $project: {
      moviename: 1,
      rating: 1,
      award_count: { $size: "$awards" }
    }
  },
  { $sort: { award_count: -1 } }
]);

7. $lookup with $facet - Multiple aggregations

db.movie_ratings.aggregate([
  {
    $facet: {
      "with_awards": [
        {
          $lookup: {
            from: "movie_awards",
            localField: "moviename",
            foreignField: "moviename",
            as: "awards"
          }
        },
        { $match: { awards: { $ne: [] } } },
        { $count: "count" }
      ],
      "without_awards": [
        {
          $lookup: {
            from: "movie_awards",
            localField: "moviename",
            foreignField: "moviename",
            as: "awards"
          }
        },
        { $match: { awards: [] } },
        { $count: "count" }
      ]
    }
  }
]);

8. $lookup with $graphLookup - Director relationships

// First add a "mentor" field to some directors
db.directors.updateOne(
  { name: "Sukumar" },
  { $set: { mentor: "S.S. Rajamouli" } }
);

// Then perform graph lookup
db.movie_ratings.aggregate([
  {
    $graphLookup: {
      from: "directors",
      startWith: "$director",
      connectFromField: "mentor",
      connectToField: "name",
      as: "director_lineage",
      maxDepth: 2
    }
  }
]);

$lookup Performance Tips

  • Create indexes on join fields
  • Use pipeline form for complex joins
  • Filter early in the pipeline before $lookup
  • Consider denormalizing frequently joined data
  • Monitor performance with explain()

Advanced Queries

Try these additional challenges:

  • Find all movies where the review contains "performance" using text search
  • Calculate average rating difference between award-winning and non-award-winning movies
  • Create a view that combines movie details with aggregated award information

More MongoDB Resources

MongoDB MCQs

Test your knowledge with practice questions

Practice MCQs
MongoDB Tricks

Advanced techniques and interview tips

View Tricks