---
title: "Core Index Principles"
description: "The first field of the index should be in the query's filter or sort condition."
type: skill
canonical_url: https://claudary.paisolsolutions.com/skills/core-indexing-principles
source: "Claudary"
difficulty: intermediate
author: "Claude Code Knowledge Pack"
date: 2026-07-10T11:19:01.628Z
license: CC-BY-4.0
attribution: "Core Index Principles — Claudary (https://claudary.paisolsolutions.com/skills/core-indexing-principles)"
---

# Core Index Principles
The first field of the index should be in the query's filter or sort condition.

## Overview

# Core Index Principles

### Compound Index Guidelines

The first field of the index should be in the query's filter or sort condition.

**Equality → Sort → Range** order is most often preferred:

- **Equality** fields first (e.g. `{field: value}`, `{$in: [...]}` with \\<= 200 elements, `{field: {$eq: value}}`)
- **Sort** fields next  
- **Range** fields last (e.g. `$gt`, `$lt`, `$gte`, `$lte`, `{$in: [...]}` with \\> 200 elements in the array, `$ne`, anchored case-sensitive `$regex`)

If equality is not very selective and range is, then ERS may perform better than ESR.

### Sort direction

Index `{a:1, b:1}` supports `sort({a:1, b:1})` and reverse `sort({a:-1, b:-1})`, but NOT mixed directions like `sort({a:1, b:-1})`. For mixed sorts, create index matching exact pattern.

### Collation Match

**Before** — Query collation differs from index collation, so the index cannot be used:

```javascript
db.users.createIndex({ name: 1 })
db.users.find({ name: "José" }).collation({ locale: "es", strength: 2 })
// Index cannot be used for query
```

**After** — Create the index with the same collation the query uses:

```javascript
db.users.createIndex({ name: 1 }, { collation: { locale: "es", strength: 2 } })
db.users.find({ name: "José" }).collation({ locale: "es", strength: 2 })
// Index can be used for query
```

**Why:** Collation must match between index and query.

# Covered Queries

A covered query retrieves data directly from the index, never accessing the actual documents. This is extremely fast and preferable when possible.

## Requirements

1. **All query fields** are in the index  
2. **All returned fields** are in the index (includes sort fields)  
3. **Inclusion projection required** \\- you must use an inclusion projection (e.g., `{ field: 1 }`) that requests only indexed fields, plus `_id: 0` if `_id` is not in the index. Exclusion projections cannot produce covered queries.  
4. **No `$exists` or null equality checks** \\- queries using `$exists` or querying for null/missing values cannot usually be covered by an index
5. **Multikey index constraints** \\- multikey indexes can cover queries under certain conditions, such as when the array field itself is not included in the projection and operators like `$elemMatch` are not used. If the array field must be projected, covering is not possible.

## Building a covered query

**Step 1:** Identify your query pattern

```javascript
db.products.find(
  { category: "electronics", inStock: true },
  { category: 1, inStock: 1, price: 1, _id: 0 }
).sort({ price: 1 })
```

**Step 2:** Create index with all accessed fields

Following ESR (Equality-Sort-Range):

```javascript
db.products.createIndex({
  category: 1,    // Equality
  inStock: 1,     // Equality
  price: 1        // Sort
})
```

**Step 3:** Project only indexed fields

- Include indexed fields in projection  
- **Exclude \\_id** unless \\_id is in the index (use `_id: 0`)  
- Don't request fields not in the index

## Common mistakes

### Forgetting to explicitly exclude  \\_id

```javascript
// NOT COVERED - _id not in index but included in result
db.products.find(
  { category: "electronics" },
  { category: 1, price: 1 }  // _id included by default!
)
```

**Fix:** Explicitly exclude \\_id

```javascript
db.products.find(
  { category: "electronics" },
  { category: 1, price: 1, _id: 0 }  // Now covered
)
```

### Requesting non-indexed fields

```javascript
// NOT COVERED - description not in index
db.products.find(
  { category: "electronics" },
  { category: 1, price: 1, description: 1, _id: 0 }
)
```

**Fix:** Only project indexed fields, or add description to index

### Array fields (multikey indexes)

```javascript
// NOT COVERED - tags is an array field and is included in projection
db.products.createIndex({ tags: 1, price: 1 })
db.products.find(
  { tags: "sale" },
  { tags: 1, price: 1, _id: 0 }
)
```

**Fix:** If the array field is not needed in the result, remove it from the projection:

```javascript
// COVERED - array field (tags) used in query but not projected
db.products.find(
  { tags: "sale" },
  { price: 1, _id: 0 }
)
```

Multikey indexes can cover queries when the array field itself is not projected and operators like `$elemMatch` are not used. If you must return the array field, the query cannot be covered.

---

Source: [Claudary](https://claudary.paisolsolutions.com/skills/core-indexing-principles) · https://claudary.paisolsolutions.com
