100 MongoDB practice problems with solutions

Tired of just watching tutorials and never really feeling sure you can handle MongoDB on your own? You’re not alone—and that frustrating feeling ends right here. This post gives you 100 MongoDB practice problems with clear, complete solutions that actually make sense.

You’ll start with everyday essentials like inserting, finding, and updating documents, then work up to truly exciting challenges: aggregation pipelines, indexing, data modeling, and performance tricks. Every problem is written in plain, simple language so you can try it yourself first, then check the solution and truly understand it—no more hunting through confusing docs.

Whether you’re just beginning to fall in love with NoSQL or you’re preparing for a dream job interview, these exercises will make learning fun, practical, and deeply rewarding. Pick a problem now and start feeling genuinely confident with MongoDB. You’ve got this!

Here are 100 MongoDB practice problems with solutions, using MongoDB shell syntax. They cover CRUD, querying, updates, indexing, aggregation, and more.

Try it: 100 Node.js practice problems with solutions

1. Switch to a Database

Switch to the database named practiceDB.

js

use practiceDB

2. Create a Collection Explicitly

Create a collection named products.

js

db.createCollection("products")

3. Insert a Single Document

Insert one product document into products with fields: namepricecategory.

js

db.products.insertOne({ name: "Laptop", price: 1200, category: "Electronics" })

4. Insert Many Documents

Insert multiple employees into an employees collection.

js

db.employees.insertMany([
  { name: "Alice", department: "HR", salary: 60000 },
  { name: "Bob", department: "Engineering", salary: 80000 },
  { name: "Charlie", department: "Engineering", salary: 75000 }
])

5. Find All Documents

Retrieve all documents from the employees collection.

js

db.employees.find()

6. Pretty Print Results

Display all employees in a readable format.

js

db.employees.find().pretty()

7. Find One Document

Find the first document where name is “Alice”.

js

db.employees.findOne({ name: "Alice" })

8. Projection: Select Specific Fields

Retrieve only name and salary from all employees, without _id.

js

db.employees.find({}, { name: 1, salary: 1, _id: 0 })

9. Equality Filter

Find employees in the “Engineering” department.

js

db.employees.find({ department: "Engineering" })

10. Comparison Operators: Greater Than

Find employees with salary greater than 70000.

js

db.employees.find({ salary: { $gt: 70000 } })

11. Greater Than or Equal

Employees with salary >= 75000.

js

db.employees.find({ salary: { $gte: 75000 } })

12. Less Than

Employees with salary < 80000.

js

db.employees.find({ salary: { $lt: 80000 } })

13. Not Equal

Find employees whose department is not “HR”.

js

db.employees.find({ department: { $ne: "HR" } })

14. Multiple Conditions (AND)

Find Engineering employees with salary > 70000.

js

db.employees.find({ department: "Engineering", salary: { $gt: 70000 } })

15. OR Operator

Find employees in either “HR” or “Finance”.

js

db.employees.find({ $or: [ { department: "HR" }, { department: "Finance" } ] })

16. AND with OR

Employees in “Engineering” with salary > 70000 OR in “HR” with any salary.

js

db.employees.find({
  $or: [
    { department: "Engineering", salary: { $gt: 70000 } },
    { department: "HR" }
  ]
})

17. IN Operator

Find employees whose department is one of [“Engineering”, “IT”].

js

db.employees.find({ department: { $in: ["Engineering", "IT"] } })

18. NOT IN

Employees not in those departments.

js

db.employees.find({ department: { $nin: ["Engineering", "IT"] } })

19. Check for Field Existence

Find documents where email field exists.

js

db.employees.find({ email: { $exists: true } })

Try it: 100 Python practice problems with solutions

20. Type Check

Find documents where salary is of type double (type 1).

js

db.employees.find({ salary: { $type: 1 } })

21. Regular Expression

Find employees whose name starts with “A”.

js

db.employees.find({ name: /^A/ })

22. Case‑insensitive Regex

Find employees with “eng” in the department name (case‑insensitive).

js

db.employees.find({ department: /eng/i })

23. Sorting Ascending

List employees ordered by salary ascending.

js

db.employees.find().sort({ salary: 1 })

24. Sorting Descending

Order by salary descending, then name ascending.

js

db.employees.find().sort({ salary: -1, name: 1 })

25. Limit Results

Get the top 3 highest‑paid employees.

js

db.employees.find().sort({ salary: -1 }).limit(3)

26. Skip

Skip the first 2 employees and return the next 2.

js

db.employees.find().skip(2).limit(2)

27. Count Documents

Count the number of employees in “Engineering”.

js

db.employees.countDocuments({ department: "Engineering" })

28. Distinct Values

Get all unique department names.

js

db.employees.distinct("department")

29. Update One Document

Increase Alice’s salary by 5000.

js

db.employees.updateOne({ name: "Alice" }, { $inc: { salary: 5000 } })

30. Update Many

Give all Engineering employees a 10% raise.

js

db.employees.updateMany(
  { department: "Engineering" },
  { $mul: { salary: 1.10 } }
)

31. Set a Field Value

Set a bonus field to 500 for HR employees.

js

db.employees.updateMany({ department: "HR" }, { $set: { bonus: 500 } })

32. Unset a Field

Remove the bonus field from all documents.

js

db.employees.updateMany({}, { $unset: { bonus: "" } })

33. Rename a Field

Rename name to fullName.

js

db.employees.updateMany({}, { $rename: { "name": "fullName" } })

34. Replace a Document

Replace Charlie’s entire document with a new one.

js

db.employees.replaceOne(
  { fullName: "Charlie" },
  { fullName: "Charlie", department: "Sales", salary: 70000, email: "charlie@example.com" }
)

35. Upsert

Update an employee with name “Diana” or insert if not found.

js

db.employees.updateOne(
  { name: "Diana" },
  { $set: { department: "Marketing", salary: 65000 } },
  { upsert: true }
)

36. Delete One Document

Delete the employee named “Bob”.

js

db.employees.deleteOne({ name: "Bob" })

37. Delete Many

Remove all employees with salary below 50000.

js

db.employees.deleteMany({ salary: { $lt: 50000 } })

38. Drop a Collection

Remove the products collection.

js

db.products.drop()

39. Create Index

Create an ascending index on salary.

js

db.employees.createIndex({ salary: 1 })

40. Compound Index

Create an index on department (ascending) and salary (descending).

js

db.employees.createIndex({ department: 1, salary: -1 })

41. Text Index

Create a text index on the name and department fields.

js

db.employees.createIndex({ name: "text", department: "text" })

42. Text Search

Search for documents containing “engineer” using the text index.

js

db.employees.find({ $text: { $search: "engineer" } })

43. Unique Index

Create a unique index on email field.

js

db.employees.createIndex({ email: 1 }, { unique: true })

44. View Indexes

List all indexes on the employees collection.

js

db.employees.getIndexes()

45. Drop an Index

Drop the index on salary.

js

db.employees.dropIndex("salary_1")

46. Aggregation: $match

Find employees with salary > 60000.

js

db.employees.aggregate([{ $match: { salary: { $gt: 60000 } } }])

47. Aggregation: $group

Count employees per department.

js

db.employees.aggregate([
  { $group: { _id: "$department", count: { $sum: 1 } } }
])

48. $group with Average

Compute average salary per department.

js

db.employees.aggregate([
  { $group: { _id: "$department", avgSalary: { $avg: "$salary" } } }
])

49. $project

Display name, department, and a computed field monthlySalary (salary / 12).

js

db.employees.aggregate([
  { $project: { name: 1, department: 1, monthlySalary: { $divide: ["$salary", 12] } } }
])

50. $sort in Aggregation

Sort departments by average salary descending.

js

db.employees.aggregate([
  { $group: { _id: "$department", avgSalary: { $avg: "$salary" } } },
  { $sort: { avgSalary: -1 } }
])

51. $limit in Aggregation

Return the top 2 highest salaries.

js

db.employees.aggregate([
  { $sort: { salary: -1 } },
  { $limit: 2 }
])

52. $unwind

Given a collection orders with an array field items, unwind it.

js

db.orders.aggregate([{ $unwind: "$items" }])

53. $unwind with preserveNullAndEmptyArrays

Unwind items keeping orders with empty or missing items.

js

db.orders.aggregate([{ $unwind: { path: "$items", preserveNullAndEmptyArrays: true } }])

54. $lookup (Join)

Join orders with customers on customerId.

js

db.orders.aggregate([
  { $lookup: {
      from: "customers",
      localField: "customerId",
      foreignField: "_id",
      as: "customer"
  } }
])

55. $lookup with Pipeline

For each department, get the employees. (Reverse join)

js

db.departments.aggregate([
  { $lookup: {
      from: "employees",
      let: { dept: "$name" },
      pipeline: [ { $match: { $expr: { $eq: ["$department", "$$dept"] } } } ],
      as: "staff"
  } }
])

56. $push to Create Array

Group employees per department and collect their names.

js

db.employees.aggregate([
  { $group: { _id: "$department", names: { $push: "$name" } } }
])

Try it: 100 Java practice problems with solutions

57. $addToSet

Collect unique salary values per department.

js

db.employees.aggregate([
  { $group: { _id: "$department", uniqueSalaries: { $addToSet: "$salary" } } }
])

58. $sum with Nested Field

Given orders with items array, compute total quantity sold per order.

js

db.orders.aggregate([
  { $addFields: { totalQty: { $sum: "$items.quantity" } } }
])

59. $bucket

Group employees into salary buckets: <50000, 50000‑100000, >=100000.

js

db.employees.aggregate([
  { $bucket: {
      groupBy: "$salary",
      boundaries: [0, 50000, 100000, Infinity],
      default: "Other",
      output: { count: { $sum: 1 } }
  } }
])

60. $facet

Get in one aggregation: number of employees per department, and average salary per department.

js

db.employees.aggregate([
  { $facet: {
      countPerDept: [{ $group: { _id: "$department", count: { $sum: 1 } } }],
      avgSalaryPerDept: [{ $group: { _id: "$department", avg: { $avg: "$salary" } } }]
  } }
])

61. $replaceRoot

Promote a nested document to top level.

js

db.orders.aggregate([
  { $lookup: { from: "customers", localField: "customerId", foreignField: "_id", as: "customer" } },
  { $unwind: "$customer" },
  { $replaceRoot: { newRoot: "$customer" } }
])

62. $merge

Write aggregation results into a new collection deptSummary.

js

db.employees.aggregate([
  { $group: { _id: "$department", avgSalary: { $avg: "$salary" } } },
  { $merge: { into: "deptSummary" } }
])

63. $out

Write aggregation results into a collection (overwrites if exists).

js

db.employees.aggregate([
  { $sort: { salary: -1 } },
  { $out: "sortedEmployees" }
])

64. $indexOfArray

Find the position of a value in an array.

js

db.orders.aggregate([
  { $project: { firstItemIndex: { $indexOfArray: ["$items.productId", "p123"] } } }
])

65. $filter

Filter array elements where quantity > 2.

js

db.orders.aggregate([
  { $project: { items: { $filter: { input: "$items", cond: { $gt: ["$$this.quantity", 2] } } } } }
])

66. Array $size

Add a field indicating the number of items in each order.

js

db.orders.aggregate([
  { $addFields: { itemCount: { $size: "$items" } } }
])

67. $slice

Return only the first 2 items from the items array.

js

db.orders.aggregate([{ $project: { firstTwo: { $slice: ["$items", 2] } } }])

68. $map over Array

For each order, create an array of item descriptions "quantity x product".

js

db.orders.aggregate([
  { $project: {
      itemsDesc: { $map: {
        input: "$items",
        as: "item",
        in: { $concat: [ { $toString: "$$item.quantity" }, " x ", "$$item.productId" ] }
      } }
  } }
])

69. $reduce

Compute total order value from items array (quantity * price) without using $sum.

js

db.orders.aggregate([
  { $project: {
      total: {
        $reduce: {
          input: "$items",
          initialValue: 0,
          in: { $add: ["$$value", { $multiply: ["$$this.quantity", "$$this.price"] } ] }
        }
      }
  } }
])

70. $cond

Create a field status: “High” if salary > 70000, else “Normal”.

js

db.employees.aggregate([
  { $addFields: { status: { $cond: { if: { $gt: ["$salary", 70000] }, then: "High", else: "Normal" } } } }
])

71. $switch

Categorize salary into “Low”, “Medium”, “High”.

js

db.employees.aggregate([
  { $addFields: {
      category: {
        $switch: {
          branches: [
            { case: { $lt: ["$salary", 50000] }, then: "Low" },
            { case: { $lte: ["$salary", 100000] }, then: "Medium" }
          ],
          default: "High"
        }
      }
  } }
])

72. $dateToString

Format a date field hireDate as “YYYY‑MM‑DD”.

js

db.employees.aggregate([
  { $project: { hired: { $dateToString: { format: "%Y-%m-%d", date: "$hireDate" } } } }
])

73. year,year,month, $dayOfMonth

Extract year, month, day from orderDate.

js

db.orders.aggregate([
  { $project: { year: { $year: "$orderDate" }, month: { $month: "$orderDate" }, day: { $dayOfMonth: "$orderDate" } } }
])

74. groupwithgroupwithfirst and $last

Get the first and last hired employee per department.

js

db.employees.aggregate([
  { $sort: { hireDate: 1 } },
  { $group: { _id: "$department", firstHired: { $first: "$name" }, lastHired: { $last: "$name" } } }
])

75. $currentDate

Set a lastModified field to the current date.

js

db.employees.updateMany({}, { $currentDate: { lastModified: true } })

76. minandminandmax in $group

Find min and max salary per department.

js

db.employees.aggregate([
  { $group: { _id: "$department", minSalary: { $min: "$salary" }, maxSalary: { $max: "$salary" } } }
])

77. $stdDevPop

Calculate standard deviation of salaries.

js

db.employees.aggregate([
  { $group: { _id: null, stdDev: { $stdDevPop: "$salary" } } }
])

78. sumwithConditional(sumwithConditional(sum and $cond)

Count the number of employees per department with salary > 70000.

js

db.employees.aggregate([
  { $group: { _id: "$department", highEarners: { $sum: { $cond: [ { $gt: ["$salary", 70000] }, 1, 0 ] } } } }
])

79. $round

Round salary to nearest thousand.

js

db.employees.aggregate([
  { $addFields: { roundedSalary: { $round: ["$salary", -3] } } }
])

80. $concat

Create full address string.

js

db.customers.aggregate([
  { $addFields: { fullAddress: { $concat: ["$city", ", ", "$country"] } } }
])

81. toUpper/toUpper/toLower

Convert all names to uppercase in output.

js

db.employees.aggregate([{ $project: { name: { $toUpper: "$name" }, department: 1 } }])

82. $arrayElemAt

Get the second element from the items array.

js

db.orders.aggregate([{ $project: { secondItem: { $arrayElemAt: ["$items", 1] } } }])

83. $reverseArray

Reverse the items array.

js

db.orders.aggregate([{ $project: { reversedItems: { $reverseArray: "$items" } } }])

84. $in (aggregation operator)

Check if a value is in an array (different from query in).Usein).UseisArray? Actually there is $in expression that checks if a value is in an array.

js

db.employees.aggregate([
  { $addFields: { isEngineer: { $in: ["$department", ["Engineering", "IT"]] } } }
])

85. $objectToArray

Convert an object to an array of key‑value pairs.

js

db.customers.aggregate([{ $project: { asArray: { $objectToArray: "$address" } } }])

86. $arrayToObject

Convert an array of key‑value pairs to an object.

js

db.customers.aggregate([
  { $project: { addressObj: { $arrayToObject: "$addressFields" } } }
])

87. $setUnion

Union of two arrays.

js

db.orders.aggregate([
  { $project: { combinedCategories: { $setUnion: ["$categories", "$recommended"] } } }
])

88. $setIntersection

Intersection of arrays.

js

db.orders.aggregate([
  { $project: { common: { $setIntersection: ["$categories", "$recommended"] } } }
])

89. $setDifference

Items in array A not in B.

js

db.orders.aggregate([
  { $project: { missingRecs: { $setDifference: ["$categories", "$recommended"] } } }
])

90. $zip

Zip two arrays together.

js

db.orders.aggregate([
  { $project: { productQuantity: { $zip: { inputs: ["$productIds", "$quantities"] } } } }
])

91. Geospatial: 2dsphere Index

Create a 2dsphere index on location field.

js

db.places.createIndex({ location: "2dsphere" })

92. $near

Find places near a point (long, lat) within 1000 meters.

js

db.places.find({
  location: {
    $near: { $geometry: { type: "Point", coordinates: [ -73.97, 40.77 ] }, $maxDistance: 1000 }
  }
})

93. $geoWithin

Find places within a specified polygon.

js

db.places.find({
  location: { $geoWithin: { $geometry: { type: "Polygon", coordinates: [[...]] } } }
})

94. Transactions (with session)

Start a session and transfer money between accounts.

js

const session = db.getMongo().startSession();
session.startTransaction();
try {
  db.accounts.updateOne({ _id: 1 }, { $inc: { balance: -100 } }, { session });
  db.accounts.updateOne({ _id: 2 }, { $inc: { balance: 100 } }, { session });
  session.commitTransaction();
} catch (error) {
  session.abortTransaction();
} finally {
  session.endSession();
}

95. BulkWrite

Perform multiple operations: insert, update, delete.

js

db.employees.bulkWrite([
  { insertOne: { document: { name: "Eve", department: "Finance", salary: 70000 } } },
  { updateOne: { filter: { name: "Alice" }, update: { $set: { salary: 65000 } } } },
  { deleteOne: { filter: { name: "Bob" } } }
])

96. Database Stats

Get statistics of the current database.

js

db.stats()

97. Collection Stats

Get storage size and document count of employees.

js

db.employees.stats()

Try it: 100 C++ practice problems with solutions

98. Explain

Explain a query plan for finding salary > 50000.

js

db.employees.find({ salary: { $gt: 50000 } }).explain("executionStats")

99. Create Capped Collection

Create a capped collection logs with a max size of 1 MB and max 1000 documents.

js

db.createCollection("logs", { capped: true, size: 1048576, max: 1000 })

100. Run Command (ping)

Ping the database to check connectivity.

js

db.runCommand({ ping: 1 })

Final Thought

One hundred problems ago, you were someone else.
Maybe a little timid, maybe aching to truly understand NoSQL, maybe craving the kind of mastery that feels almost out of reach. Today, you look back over a landscape of collections, aggregations, indexes, and pipelines — and something stirs inside you. A quiet longing for those early discovery days, when every $match and $group felt like unlocking a secret chamber. You’ll miss the late nights wrestling with a document that wouldn’t update, the gentle thrill when a complex query finally returned exactly what you desired. That sweet ache? It’s the signature of growth.

Now you’re standing on solid ground, but a new craving is already whispering — what else can I build? Let that desire pull you toward real-world projects, toward data you’ve never touched, toward the beautiful, messy, infinite world that only a developer’s heart can shape. Bookmark this page like a love letter to the learner you were — and open it again when nostalgia calls. Keep chasing that feeling.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top