Menu
CoddyTech

MongoDB Indexing Interview Questions

How indexes speed up reads: single-field, compound, multikey, unique, partial and TTL indexes, the ESR rule and covered queries.

12 questions
  1. What is an index in MongoDB, and why use one?

    A sorted structure (a B-tree) of field values with pointers to the documents. Without one, a query reads every document (a collection scan, COLLSCAN); with one, it walks only the matching keys (IXSCAN). An index also returns results already sorted. The cost: every insert, update and delete must update each index, and indexes take RAM and disk. Every collection has an index on _id.

  2. How do you create an index?

    createIndex with the fields and a direction, 1 ascending or -1 descending, plus options such as unique, name, partialFilterExpression or expireAfterSeconds. The default name joins fields and directions, like email_1. In the shell it is db.users.createIndex({ email: 1 }, { unique: true }).

    Node.js
    const { MongoClient } = require('mongodb');
    const client = new MongoClient('mongodb://localhost:27017');
    
    async function main() {
      const users = client.db('shop').collection('users');
      await users.createIndex({ email: 1 }, { unique: true });
      await users.createIndex({ city: 1, age: -1 });
      const indexes = await users.indexes();
      console.log(indexes.map((i) => i.name));
    }
    main().finally(() => client.close());
  3. Can two documents without the field share a unique index?

    Node.js
    const { MongoClient } = require('mongodb');
    const client = new MongoClient('mongodb://localhost:27017');
    
    async function main() {
      const users = client.db('shop').collection('users');
      await users.createIndex({ email: 1 }, { unique: true });
      await users.insertOne({ name: 'Asha' });
      try {
        await users.insertOne({ name: 'Ravi' });
        console.log('inserted');
      } catch (err) {
        console.log('error', err.code);
      }
    }
    main().finally(() => client.close());

    It prints error 11000. A unique index stores a missing field as null, so a second document without an email collides with the first. To make the field optional but unique when present, use a partial index: createIndex({ email: 1 }, { unique: true, partialFilterExpression: { email: { $exists: true } } }).

  4. How do you choose the field order in a compound index?

    Follow the ESR rule: Equality fields first, then Sort fields, then Range fields. For find({ status: 'paid', total: { $gt: 100 } }).sort({ date: -1 }) the index is { status: 1, date: -1, total: 1 }; putting total before date would force an in-memory sort. A compound index also serves its prefixes: { a: 1, b: 1, c: 1 } helps queries on a, on a and b, and on all three, but not on b alone.

  5. What is a multikey index?

    An index on an array field. MongoDB makes it multikey automatically and stores one index key per element, so { tags: 1 } serves find({ tags: 'node' }). Limits: in a compound multikey index, each document may have at most one indexed field that is an array; a multikey index cannot be a shard key; and long arrays mean many keys per document, which slows writes.

  6. What is a text index, and what are its limits?

    A text index tokenizes and stems string fields so you can search words with $text and sort by relevance. A collection can have only one text index (it may cover several fields), and it has no prefix, fuzzy or autocomplete matching. On MongoDB Atlas, Atlas Search (built on Lucene) is the usual choice for search features.

    db.articles.createIndex({ title: 'text', body: 'text' })
    db.articles.find({ $text: { $search: 'index tuning' } }, { score: { $meta: 'textScore' } })
      .sort({ score: { $meta: 'textScore' } })
    
  7. What is a TTL index?

    A single-field index on a date field with expireAfterSeconds: a background task deletes each document once that many seconds have passed since its date. It suits sessions, one-time codes and temporary logs. The task runs every 60 seconds, so documents can outlive their expiry a little, and documents whose field is not a date never expire.

    db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 })
    // expire at a time stored in each document
    db.tokens.createIndex({ expiresAt: 1 }, { expireAfterSeconds: 0 })
    
  8. What is the difference between a partial and a sparse index?

    A sparse index skips documents that lack the field. A partial index (3.2+) skips documents that do not match a filter you give, such as { status: 'active' }; it can do everything sparse does and is the recommended choice. Both are smaller and cheaper to maintain, but the planner uses one only when the query's filter guarantees the index holds every match, so a query without status: 'active' ignores that partial index.

  9. What is a covered query?

    A query answered from the index alone: every field in the filter and the projection is in the index, so MongoDB never fetches the documents. explain shows no FETCH stage and totalDocsExamined: 0. Exclude _id unless it is in the index; a field that holds an array cannot be covered.

    db.users.createIndex({ email: 1, name: 1 })
    db.users.find({ email: 'asha@example.com' }, { _id: 0, email: 1, name: 1 })
    
  10. How do you check whether a query uses an index?

    Run it with explain('executionStats'). In the winning plan, IXSCAN means an index scan and COLLSCAN a full scan. Then compare nReturned, totalKeysExamined and totalDocsExamined: in a good plan all three are close. Thousands of documents examined to return ten means a missing or badly ordered index. The SQL counterpart is EXPLAIN QUERY PLAN.

    db.orders.find({ status: 'paid' }).sort({ date: -1 }).explain('executionStats')
    
  11. Can a collection have too many indexes?

    Yes. Each index adds work to every insert and to every update of its fields, takes disk space, and competes for RAM with your data. The hard limit is 64 indexes per collection, but writes suffer long before that. Find unused ones with the $indexStats stage, and hide an index (hideIndex, 4.4+) to test removing it before you drop it.

  12. Does the direction of fields in a compound index matter?

    For a single-field index, no: MongoDB can walk it either way. For a compound index used to sort, yes: { date: 1, score: -1 } supports sort({ date: 1, score: -1 }) and its exact reverse, sort({ date: -1, score: 1 }), but not sort({ date: 1, score: 1 }), which needs an in-memory sort.

Coddy programming languages illustration

Learn to code with Coddy

Get started