MongoDBMultikey Indexes

Multikey Indexes

When you index a field whose value is an array, MongoDB automatically builds what's called a multikey index — one index entry per array element rather than one entry per document. No special syntax is required; MongoDB detects the array shape at index-build time.

How Array Values Get Indexed

One document, multiple index entries

JS
db.posts.createIndex({ tags: 1 })

db.posts.insertOne({ _id: 1, title: "Intro to MongoDB", tags: ["mongodb", "nosql", "database"] })
// Creates THREE separate index entries:
//   "mongodb"  → _id: 1
//   "nosql"    → _id: 1
//   "database" → _id: 1
// All three entries point back to the SAME document.

A single-element match is enough

JS
db.posts.find({ tags: "nosql" })   // matches the document above — one array element is enough
Note
A multikey index can make a collection's total index entry count larger than its document count — a collection of 10,000 posts averaging 5 tags each produces roughly 50,000 index entries in a multikey index on tags.
Checking isMultikey in explain()

isMultiKey in the explain output

JS
db.posts.find({ tags: "nosql" }).explain()
{
  queryPlanner: {
    winningPlan: {
      stage: 'FETCH',
      inputStage: {
        stage: 'IXSCAN',
        indexName: 'tags_1',
        isMultiKey: true,                 // confirms this index indexes an array field
        multiKeyPaths: { tags: ['tags'] }
      }
    }
  }
}
Tip
isMultiKey: true plus multiKeyPaths tells you exactly which field(s) in the index are the array-valued ones — useful when a compound index mixes scalar and array fields and you're not sure which part triggered multikey behavior.
The Big Limitation: One Array Field Per Compound Index

A compound index can include at most one array-valued field. Trying to create a compound index on two array fields at once fails outright — MongoDB has no way to represent the cross-product of two independently-varying arrays as a single flat B-tree efficiently.

This fails — two array fields in one compound index

JS
db.posts.createIndex({ tags: 1, categories: 1 })
// If BOTH "tags" and "categories" are arrays on the same documents:
// Error: cannot index parallel arrays [categories] [tags]

This works — one array field, one scalar field

JS
db.posts.createIndex({ tags: 1, publishedAt: -1 })   // tags is an array, publishedAt is a scalar — fine
Warning
The "parallel arrays" restriction applies per **document**, not per field definition — MongoDB only errors if it actually finds a document where both indexed fields hold arrays at the same time. A schema where this only happens rarely can still build the index successfully until the first offending document appears, so this can surface unexpectedly during a later insert.
$elemMatch Queries with a Multikey Index

When the array holds embedded documents and you filter on multiple sub-fields together, $elemMatch combined with a compound multikey index can still be served efficiently — as long as the index covers the fields inside the array being matched.

Indexing fields inside an array of sub-documents

JS
db.orders.createIndex({ "items.sku": 1, "items.qty": 1 })

db.orders.find({
  items: { $elemMatch: { sku: "WIDGET-42", qty: { $gte: 2 } } }
})
// Can use the compound index on items.sku / items.qty when both
// conditions apply to the SAME array element, matching $elemMatch semantics.
Note
A compound index built from two fields of the same array of sub-documents (like items.sku and items.qty above) is not the "two array fields" restriction — that restriction is about two different, independently-varying top-level arrays, not two fields nested inside the same array of embedded documents.
Bounds and Performance

Because a multikey index has one entry per array element, a query that matches many elements across many documents can examine far more index keys than the number of documents actually returned — watch totalKeysExamined vs nReturned in explain() just like any other index.

Checking multikey index efficiency

JS
db.posts.find({ tags: { $in: ["mongodb", "nosql", "database"] } }).explain("executionStats")
// $in against a multikey index scans keys for EACH value in the $in list —
// totalKeysExamined can be notably higher than a simple equality lookup
Warning
Very large arrays (hundreds or thousands of elements per document) make multikey indexes expensive to maintain — every insert or update to that array field rewrites potentially many index entries. If an array field regularly grows large and unbounded, reconsider the schema (see the Documents & Collections page on unbounded arrays) before leaning on a multikey index over it.
  • Indexing an array field is automatic — MongoDB detects the array and builds a multikey index with one entry per element.

  • A single array value matching is enough to satisfy an equality filter against a multikey-indexed field.

  • A compound index can include at most one array-valued field per document — "parallel arrays" on the same document will error.

  • isMultiKey: true and multiKeyPaths in explain() confirm which fields triggered multikey behavior.

  • Use $elemMatch with a compound index over multiple sub-document fields to correctly match conditions against the SAME array element.