Single-Field Indexes
A single-field index covers exactly one field. It's the simplest index type, and the one you'll create most often to support equality and range filters, plain sorts, and existence checks on an individual field.
Creating One
Ascending single-field index
db.products.createIndex({ price: 1 })
db.products.find({ price: { $gte: 10, $lte: 50 } }) // uses the indexDoes Direction Matter for a Single Field?
For a single-field index, ascending (1) vs descending (-1) makes no practical difference — a B-tree can be walked in either direction with equal efficiency. sort({ price: 1 }) and sort({ price: -1 }) are both served just as well by an index created as { price: 1 }.
One index, both sort directions
db.products.createIndex({ price: 1 })
db.products.find().sort({ price: 1 }) // walks the index forward
db.products.find().sort({ price: -1 }) // walks the SAME index backward — equally fastIndexing Nested Fields (Dot Notation)
Indexing an embedded field
db.users.createIndex({ "address.city": 1 })
db.users.find({ "address.city": "Toronto" }) // uses the indexIndexing Array Fields — Multikey
Create a single-field index on a field that happens to hold an array, and MongoDB automatically builds it as a multikey index: one index entry per array element, per document, rather than one entry per document.
An index on an array field becomes multikey automatically
db.posts.createIndex({ tags: 1 })
db.posts.insertOne({ _id: 1, tags: ["mongodb", "nosql", "database"] })
// This ONE document creates THREE index entries — one per tag —
// each pointing back to the same document.
db.posts.find({ tags: "nosql" }) // uses the multikey indexSee the dedicated Multikey Index page for the full mechanics and limitations — the important thing here is that you don't do anything special to opt in; MongoDB detects the array and builds a multikey index automatically.
The sparse Option
By default, an index includes an entry for every document, even ones missing the indexed field (indexed as if the value were null). A sparse index skips documents that don't have the field at all — smaller index, but queries against it may miss documents you'd expect to match null.
Sparse index — skip documents missing the field
db.users.createIndex({ referralCode: 1 }, { sparse: true, unique: true })
// Only documents that HAVE a referralCode are indexed and checked for uniqueness.
// Documents with no referralCode at all don't collide with each other,
// unlike a plain unique index where multiple missing fields would all
// be treated as null and collide.null — so a second document also missing that field triggers a duplicate key error. If a field is optional and you want a unique index on it, combine unique: true with sparse: true (or a partial filter expression) so multiple documents can all omit it without colliding.Case-Insensitive Indexing via Collation
A plain index compares strings byte-by-byte (case-sensitive). To support case-insensitive equality/sort queries efficiently, build the index with a collation that matches the queries you'll run against it.
Case-insensitive index via collation
db.users.createIndex(
{ email: 1 },
{ collation: { locale: "en", strength: 2 } } // strength 2 = case-insensitive
)
// This query can use the collated index because it specifies the SAME collation
db.users.find({ email: "Alice@Example.com" }).collation({ locale: "en", strength: 2 }).collation() call uses the server's default (binary) comparison and will not use a collated index, even if one exists on the same field.Inspecting Indexes
test> db.users.getIndexes()
[
{ v: 2, key: { _id: 1 }, name: '_id_' },
{ v: 2, key: { 'address.city': 1 }, name: 'address.city_1' },
{
v: 2,
key: { email: 1 },
name: 'email_1',
collation: { locale: 'en', strength: 2, ... }
}
]Direction (
1vs-1) is irrelevant for a single-field index — it serves both sort directions equally well.Indexing a nested field uses dot notation:
{ "address.city": 1 }.Indexing an array field is automatic — MongoDB builds a multikey index without any special syntax.
sparse: trueexcludes documents missing the field — usually paired withunique: trueon optional fields.Case-insensitive queries need both a collated index AND a matching
.collation()on the query to actually use it.