pencils ready ✎

MongoDB MCQs multiple-choice questions with answers & explanations

All 22 MongoDB quiz questions on one page. Pick an answer in your head, then open Show answer to check it and read why. Want a score and a timer? Take them as a quiz instead.

  1. 1.

    Which documents does the find() return?

    mid
    db.scores.insertMany([
      { _id: 1, results: [82, 85, 88] },
      { _id: 2, results: [75, 88, 89] }
    ]);
    
    db.scores.find({ results: { $gte: 80, $lt: 85 } });
    1. AOnly _id: 1
    2. BOnly _id: 2
    3. CBoth documents
    4. DNeither document
    Show answer

    Answer: C (Both documents)

    Without $elemMatch, each condition on an array can be satisfied by a different element. In _id: 2, 88 satisfies $gte: 80 and 75 satisfies $lt: 85, so it matches too. To require one element between 80 and 85, use { results: { $elemMatch: { $gte: 80, $lt: 85 } } }, which returns only _id: 1.

  2. 2.

    What do the first 4 bytes of an ObjectId contain?

    easy
    1. AA random value unique to the machine and process
    2. BA timestamp in seconds since the Unix epoch
    3. CA counter that increments per client process
    4. DA hash of the database and collection name
    Show answer

    Answer: B (A timestamp in seconds since the Unix epoch)

    An ObjectId is 12 bytes: a 4-byte timestamp (seconds since the Unix epoch), a 5-byte random value generated once per process, and a 3-byte incrementing counter that starts at a random value. That is why getTimestamp() can recover the creation time.

  3. 3.

    On MongoDB 5.0 or later, what is the implicit default write concern for a three-member replica set with no arbiters?

    mid
    1. A{ w: "majority" }
    2. B{ w: 1 }
    3. C{ w: 0 }
    4. D{ w: 3, j: true }
    Show answer

    Answer: A ({ w: "majority" })

    Since 5.0 the implicit default is w: "majority". The exception is some arbiter setups: if the number of data-bearing voting members is not greater than the voting majority (for example primary-secondary-arbiter), the default becomes { w: 1 }.

  4. 4.

    Following the ESR guideline, which index best supports this query?

    mid
    db.orders.find({ status: "A", qty: { $gt: 10 } }).sort({ date: -1 });
    1. A{ qty: 1, status: 1, date: -1 }
    2. B{ status: 1, qty: 1, date: -1 }
    3. C{ date: -1, qty: 1, status: 1 }
    4. D{ status: 1, date: -1, qty: 1 }
    Show answer

    Answer: D ({ status: 1, date: -1, qty: 1 })

    ESR puts Equality fields first (status), then the Sort field (date), then Range fields (qty). Putting the range on qty before date would leave the matching keys out of date order and force an in-memory sort.

  5. 5.

    With only the index { email: 1, name: 1 } (plus the default _id index), which query is covered?

    mid
    1. Adb.users.find({ email: "a@x.io" }, { name: 1 })
    2. Bdb.users.find({ email: "a@x.io" }, { _id: 0, name: 1, age: 1 })
    3. Cdb.users.find({ email: null }, { _id: 0, name: 1 })
    4. Ddb.users.find({ email: "a@x.io" }, { _id: 0, name: 1 })
    Show answer

    Answer: D (db.users.find({ email: "a@x.io" }, { _id: 0, name: 1 }))

    A covered query needs every filtered and returned field in one index. The first option also returns _id, which is not in the index; the second returns age; and a filter comparing a field to null cannot be covered. Excluding _id and returning only indexed fields lets MongoDB skip the FETCH stage.

  6. 6.

    No document matches the filter. Apart from _id, which document does this upsert insert?

    mid
    db.inventory.updateOne(
      { sku: "X1", qty: { $lt: 5 } },
      { $set: { status: "low" }, $setOnInsert: { createdBy: "job" } },
      { upsert: true }
    );
    1. A{ sku: "X1", qty: { $lt: 5 }, status: "low", createdBy: "job" }
    2. B{ sku: "X1", status: "low", createdBy: "job" }
    3. C{ sku: "X1", status: "low" }
    4. D{ status: "low", createdBy: "job" }
    Show answer

    Answer: B ({ sku: "X1", status: "low", createdBy: "job" })

    An upsert builds the new document from the equality conditions in the filter (sku), then applies the update operators, including $setOnInsert, which runs only on insert. Comparison conditions such as qty: { $lt: 5 } are not copied into the new document.

  7. 7.

    How often does the background task that removes expired documents from TTL indexes run?

    easy
    1. AThe instant each document expires
    2. BOnce every hour, on the hour
    3. CEvery 60 seconds
    4. DWhenever the collection is queried
    Show answer

    Answer: C (Every 60 seconds)

    The TTL monitor runs every 60 seconds, so documents can remain for a while after they expire, longer under heavy load. If expired data must never be visible, also filter on the date field in your queries.

  8. 8.

    A collection has createIndex({ email: 1 }, { unique: true }). What happens when you insert two documents that have no email field?

    mid
    1. AThe second insert fails with a duplicate key error
    2. BBoth succeed because missing fields are not indexed
    3. CBoth fail because a unique field becomes required
    4. DMongoDB converts the index to a sparse index
    Show answer

    Answer: A (The second insert fails with a duplicate key error)

    A unique index stores a null key for documents missing the field, and only one document can hold that null. To allow many documents without an email, use a partial unique index with partialFilterExpression: { email: { $exists: true } }.

  9. 9.

    The document is { _id: 1, tags: ["a"] }. What is tags after this update?

    easy
    db.posts.updateOne({ _id: 1 }, { $push: { tags: ["b", "c"] } });
    1. A["a", "b", "c"]
    2. B["b", "c"]
    3. C["a", ["b", "c"]]
    4. D["a", ["b"], ["c"]]
    Show answer

    Answer: C (["a", ["b", "c"]])

    $push appends its value as a single element, so pushing an array nests it. To append each value separately, use { $push: { tags: { $each: ["b", "c"] } } }.

  10. 10.

    The document is { _id: 1, tags: ["a", "b"] }. What is tags after this update?

    easy
    db.posts.updateOne({ _id: 1 }, { $addToSet: { tags: { $each: ["b", "c"] } } });
    1. A["a", "b", "b", "c"]
    2. B["a", "b", ["b", "c"]]
    3. C["b", "c"]
    4. D["a", "b", "c"]
    Show answer

    Answer: D (["a", "b", "c"])

    $addToSet adds a value only if it is not already in the array, and $each applies that to every listed value. "b" is already present, so only "c" is added. Without $each, the whole array ["b", "c"] would be added as one element.

  11. 11.

    What is the default read preference for a replica set connection?

    easy
    1. Anearest
    2. Bprimary
    3. CsecondaryPreferred
    4. DprimaryPreferred
    Show answer

    Answer: B (primary)

    By default all reads go to the primary, and they fail if no primary is available. primaryPreferred falls back to secondaries during failover, while secondaryPreferred and nearest accept possibly stale data from secondaries.

  12. 12.

    The orders collection has an index on { total: 1 }. Can the $match in this pipeline use it?

    mid
    db.orders.aggregate([
      { $group: { _id: "$customerId", total: { $sum: "$amount" } } },
      { $match: { total: { $gt: 1000 } } }
    ]);
    1. AYes, the optimizer moves the $match ahead of $group
    2. BYes, a $match can use indexes wherever it appears
    3. CNo, this total only exists after $group runs
    4. DOnly when the pipeline runs with allowDiskUse: true
    Show answer

    Answer: C (No, this total only exists after $group runs)

    Here total is computed by $group, so the $match filters grouped results in memory and no collection index applies. Only stages at the start of a pipeline read from the collection with indexes. The optimizer only moves a $match earlier when it does not depend on computed fields.

  13. 13.

    Which deployment does not support multi-document transactions?

    easy
    1. AA three-member replica set
    2. BA sharded cluster running 4.2 or later
    3. CA five-member replica set
    4. DA standalone mongod server
    Show answer

    Answer: D (A standalone mongod server)

    Multi-document transactions need a replica set (since 4.0) or a sharded cluster (since 4.2). A standalone server does not support them. You can convert a standalone into a single-member replica set for development.

  14. 14.

    You shard an events collection on the ranged key { createdAt: 1 }. What is the main problem?

    mid
    1. AEvery new insert lands in the chunk holding the highest values
    2. BQueries filtering on a time range must be sent to every shard
    3. CA shard key on a date field cannot be backed by an index
    4. DDocuments that lack createdAt are always rejected by mongos
    Show answer

    Answer: A (Every new insert lands in the chunk holding the highest values)

    With an always-increasing key, all new documents fall into the chunk whose upper bound is maxKey, so one shard takes every insert. Ranged keys actually keep time-range queries targeted. Hashed sharding or a compound key such as { deviceId: 1, createdAt: 1 } spreads the writes.

  15. 15.

    Why does find().sort({ createdAt: -1 }).skip(100000).limit(20) get slow even with an index on createdAt?

    mid
    1. Askip() stops the query planner from using any index
    2. Blimit() runs before skip() and discards the results
    3. CThe server still walks past all 100,000 skipped entries
    4. DThe driver downloads every skipped document to the client
    Show answer

    Answer: C (The server still walks past all 100,000 skipped entries)

    The index supplies the order, but the server still has to step over every skipped entry, so cost grows with page depth. Range-based pagination, filtering on values after the last createdAt and _id seen, turns each page into an index seek.

  16. 16.

    The winning plan in explain() output has a COLLSCAN stage. What does that mean?

    easy
    1. AThe query was answered entirely from an index
    2. BThe query read every document in the collection
    3. CThe query was broadcast to every shard in the cluster
    4. DThe query used a compound index on several fields
    Show answer

    Answer: B (The query read every document in the collection)

    COLLSCAN is a full collection scan: no index was used to narrow the search. An index-backed plan shows IXSCAN, usually followed by FETCH; a covered query has no FETCH and examines zero documents.

  17. 17.

    An order has a customerId with no matching customer. What happens to it in this pipeline?

    mid
    db.orders.aggregate([
      { $lookup: { from: "customers", localField: "customerId",
                   foreignField: "_id", as: "customer" } },
      { $unwind: "$customer" }
    ]);
    1. AIt is dropped from the output
    2. BIt is output with customer: null
    3. CIt is output with customer: []
    4. DThe whole pipeline fails with an error
    Show answer

    Answer: A (It is dropped from the output)

    $lookup is a left outer join, so the order first gets customer: []. $unwind then outputs nothing for an empty array, so the order disappears. Use { $unwind: { path: "$customer", preserveNullAndEmptyArrays: true } } to keep it.

  18. 18.

    The collection has the index { tags: 1, sizes: 1 }. What happens when you insert this document?

    hard
    db.products.insertOne({ tags: ["sale", "new"], sizes: ["S", "M"] });
    1. AIt succeeds and creates four index keys
    2. BIt succeeds, but only tags is indexed
    3. CIt succeeds and the index becomes hidden
    4. DIt fails: two indexed fields are arrays
    Show answer

    Answer: D (It fails: two indexed fields are arrays)

    In a compound multikey index, each document can have at most one indexed field whose value is an array. Once the index exists, inserting a document where both tags and sizes are arrays is rejected.

  19. 19.

    What does validationLevel: "moderate" do for a collection with a $jsonSchema validator?

    hard
    1. AUpdates to already-invalid documents skip validation
    2. BInvalid writes are accepted, and each violation is logged
    3. CRules are checked on inserts only and never on updates
    4. DRules are checked by a background job instead of on writes
    Show answer

    Answer: A (Updates to already-invalid documents skip validation)

    With moderate, inserts and updates to currently valid documents are validated, but updates to existing documents that do not match the rules are not required to pass. Accepting invalid writes and logging them is validationAction: "warn", a separate setting. The default level is strict.

  20. 20.

    In mongosh, what does db.jobs.findOneAndUpdate(filter, update) return by default?

    easy
    1. AAn object with matchedCount and modifiedCount
    2. BThe matched document as it was before the update
    3. CThe matched document after the update was applied
    4. DOnly the _id of the document it modified
    Show answer

    Answer: B (The matched document as it was before the update)

    It returns the original document by default. Pass returnDocument: "after" (or returnNewDocument: true) to get the updated version. updateOne is the method that returns counts such as matchedCount and modifiedCount.

  21. 21.

    The users collection is sharded on { userId: "hashed" }. Which query can mongos route to a single shard?

    hard
    1. Adb.users.find({ userId: { $gt: 40, $lt: 50 } })
    2. Bdb.users.find({ email: "a@x.io" })
    3. Cdb.users.find({ userId: 42 })
    4. Ddb.users.find({}).sort({ userId: 1 })
    Show answer

    Answer: C (db.users.find({ userId: 42 }))

    An equality match on a hashed shard key can be hashed and targeted to one shard. Range queries on the key become broadcast, because nearby values are scattered by the hash, and queries without the shard key are scatter-gather.

  22. 22.

    A write with { w: "majority", wtimeout: 5000 } returns a write concern timeout error. What can you conclude about the write?

    hard
    1. AIt was rolled back on every member of the set
    2. BIt may be applied and could still replicate
    3. CIt was never applied on the primary at all
    4. DThe server queues it and retries automatically
    Show answer

    Answer: B (It may be applied and could still replicate)

    wtimeout only limits how long the client waits for acknowledgment. MongoDB does not undo modifications that succeeded before the timeout, and the write may still reach a majority later, so retries must be idempotent.

esc