Filter concepts by levelShowing all levels.

MongoDB · Multikey and Array Indexes

Multikey and Array Indexes

How multikey status is detected, the compound restriction, and designing arrays with indexing in mind

  • Detected from datathe first array-valued document flips it
  • One array field per documentin a compound index — the hard restriction
  • Size ≈ Σ(array length)not document count
  • Bound before indexing$slice caps both document and index growth

1.When an index becomes multikey

An index becomes multikey the moment any document indexed by it stores an array in the indexed field — MongoDB decides this from the actual data at write time, not from a declared schema. It is a property of the index's current data, and it can flip from scalar to multikey the instant one array-valued document is inserted.

Key features

  • MongoDB detects multikey-ness from real inserted data, not from a schema declaration
  • The very first document with an array in the indexed field flips the index to multikey
  • Once an index is marked multikey, it generally stays marked multikey even if later documents are all scalar
  • A validator (section 9) can constrain a field's type to prevent this from happening unintentionally
  • Multikey status affects the compound-index array restriction and sort behavior covered by this section

Command

text
// No syntax to set — MongoDB detects multikey status automatically from the data at write time

Multikey status is detected from real data, not declared — the first document with an array in the indexed field flips it, and it generally stays flipped. Enforce a field's scalar-ness with a validator if the index design depends on it.

2.Hashed-index and sort limitations on multikey fields

Two limitations beyond the compound restriction: a hashed index cannot be built on an array field at all, and sorting on a multikey-indexed field frequently forces MongoDB to fall back to an in-memory sort rather than using the index's own order.

Key features

  • A hashed index cannot be created on a field that holds arrays — hashed indexes are incompatible with multikey entirely
  • Sorting on a multikey field often cannot use the index's own order and falls back to an in-memory sort
  • The in-memory sort fallback happens even when the multikey field is indexed, if the sort involves that field's multiple values ambiguously
  • A multikey index cannot be used as a shard key's index directly
  • These limitations are consequences of the same "an array has no single position" fact underlying the compound-multikey restriction

Command

text
// A hashed index rejects array-holding data outright; a sort on a multikey field may need explain() to confirm it isn't falling back to memory

Hashed indexes reject array-holding fields outright. Sorting on a multikey-indexed field often falls back to an in-memory sort even though the field is indexed — verify with explain(), don't assume from the scalar-field case.

3.The compound multikey restriction

A compound index can have at most one field that is an array, per document. createIndex({ genres: 1, year: 1 }) is fine if only genres is ever an array — but if any single document has both genres and year as arrays, the index creation (or the offending insert) fails outright.

Key features

  • At most one field in a compound index may hold an array value, per document
  • This is checked per document, not per index definition — different documents can have different fields be the array
  • Violating it on insert/update fails the write, not silently truncating or picking one field
  • Violating it at index-creation time (existing data already breaks the rule) fails the createIndex call
  • Hashed indexes cannot be multikey at all — a stricter, separate restriction

Compound index { genres: 1, year: 1 } — allowed vs. rejected

Compound index { genres: 1, year: 1 } — allowed vs. rejected
DocumentResult
{ genres: ["Drama", "Action"], year: 2020 }allowed — only genres is an array
{ genres: "Drama", year: [2020, 2021] }allowed — only year is an array
{ genres: ["Drama"], year: [2020, 2021] }rejected — both fields are arrays
At most one array field per document, in a compound index

Allowed

genres: array

year: scalar

year: array

genres: scalar

Rejected

genres AND year

both arrays — write fails

  • Allowed
    • genres: array — year: scalar
    • year: array — genres: scalar
  • Rejected
    • genres AND year — both arrays — write fails

Command

text
// At most one field per document can be an array, across all fields in a compound index

A compound index allows at most one array field per document — two array-valued fields together in the same compound index fail the write. Anticipate this if both candidate fields could realistically be arrays.

4.How array cardinality affects index size

A multikey index has roughly one entry per array element per document — a document with a 50-element array contributes 50 index entries, not one. Index size, build time, and per-write update cost all scale with total element count across the collection, not document count.

Key features

  • Multikey index size scales with total array-element count, not document count
  • A write that adds N elements to an array adds roughly N new index entries
  • High-cardinality arrays (many, or highly varied, elements) make for larger, costlier-to-maintain indexes
  • This is the same underlying cost the bounded-vs-unbounded-arrays concept warns about, seen from the index side
  • Index build time on a collection with large arrays is correspondingly longer than on scalar fields

Command

text
// Roughly: multikey index entries ≈ sum of array lengths across the collection, not the document count

A multikey index has roughly one entry per array element — its size scales with total element count across the collection, not document count. An unbounded or high-cardinality array makes for a correspondingly larger, costlier index.

5.Designing arrays with bounded growth, for indexing

Applied specifically to indexed arrays: enforce a cap ($slice, application logic, or referencing the overflow into its own collection) rather than letting an indexed array grow without limit — the multikey index cost compounds the same unbounded-growth risk that document size already carries.

Key features

  • Enforcing an array bound (e.g. $slice) caps both document growth and multikey index growth together
  • An unbounded indexed array is doubly expensive: bigger document, and a bigger, still-growing index
  • Referencing an unbounded relationship into its own collection avoids indexing an ever-growing array entirely
  • Design the bound before indexing, not after the index has already grown large enough to be a problem
  • This is the same bounded-vs-unbounded judgment call from data modeling, now applied specifically to indexed fields

Command

text
$push: { arrayField: { $each: [item], $slice: -N } }  // keeps an indexed array from growing past N elements

Bound an array before indexing it — $slice or referencing the overflow into its own collection caps both document growth and multikey index growth together, since they share the same root cause.

Remember

  • Multikey status is detected from real inserted data, not declared — the first array flips it, usually for good.
  • A compound index allows at most one array field per document — two together fails the write.
  • Multikey index size scales with total array elements, not document count — large/unbounded arrays cost more.
  • Hashed indexes reject arrays outright; sorting on a multikey field often falls back to an in-memory sort.

Pro tip

  • Bound an indexed array ($slice, or reference the overflow out) before indexing it — this caps document growth and index growth together.
  • Check explain() for a SORT stage when sorting on a multikey field — being indexed does not guarantee an index-supported sort here.

Next up

  • Partial, Sparse, Unique, and TTL Indexes
  • Query Planning
  • explain() and Performance Analysis

Sources

  • Multikey indexes — mongodb.com/docs/manual/core/indexes/index-types/index-multikey/
  • Checked 2026-08-21

Spotted a mistake on this page? Tell us.