> For the complete MongoDB documentation index, see www.mongodb.com/docs/llms.txt

<!--
Tab options on this page. Append to the .md URL to filter:
  ?tabs=<id,...>   select specific tabs (e.g. ?tabs=nodejs,shell)
  ?allTabs=true    include every tab
  (no param)       default: one tab per tabset

Available tabs:
  other tabs: classic-sample-output, sbe-sample-output, unsharded, sharded, cbr
-->

# Explain Results

To return information on [query plans](https://www.mongodb.com/docs/manual/core/query-plans.md#std-label-query-plans-query-optimization) and execution statistics of the query plans, MongoDB provides the following methods:

- [`db.collection.explain()`](https://www.mongodb.com/docs/manual/reference/method/db.collection.explain.md#mongodb-method-db.collection.explain)

- [`cursor.explain()`](https://www.mongodb.com/docs/manual/reference/method/cursor.explain.md#mongodb-method-cursor.explain)

To learn about important explain result fields and how to interpret them, see [Interpret Explain Plan Results.](https://www.mongodb.com/docs/manual/tutorial/analyze-query-plan.md#std-label-interpret-explain-plan)

**Important:**

`explain` ignores the plan cache. Instead, a set of candidate plans are generated, and a winner is chosen without consulting the plan cache. Furthermore, `explain` prevents the MongoDB query planner from caching the winning plan.

**Note:**

Only the most important output fields are shown on this page, and fields for internal use are not documented. The fields listed in the output are subject to change.

## Explain Output Structure

The `explain` results present the query plans as a tree of stages. The output structure can differ based on which query engine the operation uses. Operations can use the classic query engine or the [slot-based execution query engine.](https://www.mongodb.com/docs/manual/reference/sbe.md#std-label-sbe-landing)

This structure applies to [`db.collection.find()`](https://www.mongodb.com/docs/manual/reference/method/db.collection.find.md#mongodb-method-db.collection.find) and to commands that use the same query system, such as [`count`](https://www.mongodb.com/docs/manual/reference/command/count.md#mongodb-dbcommand-dbcmd.count), [`distinct`](https://www.mongodb.com/docs/manual/reference/command/distinct.md#mongodb-dbcommand-dbcmd.distinct), [`update`](https://www.mongodb.com/docs/manual/reference/command/update.md#mongodb-dbcommand-dbcmd.update), and [`findAndModify`](https://www.mongodb.com/docs/manual/reference/command/findandmodify.md#mongodb-dbcommand-dbcmd.findAndModify). Aggregation operations return a different structure that has a top-level `stages` array. To learn how to read aggregation explain output, see [Aggregation Explain Output.](https://www.mongodb.com/docs/manual/reference/explain-results.md#std-label-explain-output-aggregation)

To see how the output structure can differ between the two execution engines, see the following examples:

### Classic Execution Engine

```javascript
winningPlan: {
   stage: <STAGE1>,
   ...
   inputStage: {
      stage: <STAGE2>,
      ...
      inputStage: {
         stage: <STAGE3>,
         ...
      }
   }
},
```

Each stage passes its resulting documents or index keys to the parent node. The leaf nodes access the collection or the indices. The internal nodes use the documents or the index keys that result from the child nodes. The root node indicates the stage that MongoDB ultimately derives the result set from.

Stages are descriptive of the operation. For example:

- `COLLSCAN` for a collection scan

- `IXSCAN` for scanning index keys

- `FETCH` for retrieving documents

- `GROUP` for grouping documents

- `SHARD_MERGE` for merging results from shards

- `SHARDING_FILTER` for filtering out orphan documents from shards

- `TS_MODIFY` for modifying a time series collection

- `BATCHED_DELETE` for multiple document deletions that are batched together internally (starting in MongoDB 6.1)

- `EOF` for when a stage is end-of-stream

- `EXPRESS` stages for a limited set of queries that can bypass regular query planning to use optimized index scan plans *(New in
  version 8.0.)*

  `EXPRESS` stages can be one of the following:

  - `EXPRESS_CLUSTERED_IXSCAN`

  - `EXPRESS_DELETE`

  - `EXPRESS_IXSCAN`

  - `EXPRESS_UPDATE`

## Explain Output for MongoDB 5.1 and Later

This section shows the `explain` output for MongoDB 5.1 and later. To see the explain output for older versions of MongoDB, refer to the documentation for that version.

Integer field.

`explainVersion` is the output format version for the plan, such as `"1"` or `"2"`.

**New in version 5.1**

### `queryPlanner`

[`explain.queryPlanner`](https://www.mongodb.com/docs/manual/reference/explain-results.md#mongodb-data-explain.queryPlanner) information details the plan selected by the [query optimizer.](https://www.mongodb.com/docs/manual/core/query-plans.md#std-label-read-operations-query-optimization)

**Note:**

Starting in MongoDB 8.3, multi-planning with a CBR backup is the default plan selection mechanism for eligible queries. For a short trial period, the multi-planner attempts to find a plan capable of returning a result set within this short timeframe. If the attempt is unsuccessful, MongoDB applies a set of rules to determine whether the multi-planner should continue or if CBR should evaluate each node in the plan to determine the optimal plan.

For more information, see [Query Plan Options.](https://www.mongodb.com/docs/manual/core/query-plans.md#std-label-query-plan-options)

These examples may combine the output structures of the classic and slot-based execution engines. They are not meant to be representative. Your output may differ significantly.

### Unsharded Collections

For unsharded collections, `explain` returns the following `queryPlanner` information:

```javascript
queryPlanner: {
   namespace: <string>,
   indexFilterSet: <boolean>,
   parsedQuery: {
      ...
   },
   planCacheShapeHash: <hexadecimal string>,
   planCacheKey: <hexadecimal string>,
   maxIndexedOrSolutionsReached: <boolean>,
   maxIndexedAndSolutionsReached: <boolean>,
   maxScansToExplodeReached: <boolean>,
   winningPlan: {
     stage: <STAGE1>,
     type: <string>,
     inputStage: {
       stage: <string>,
       ...
     }
   },
   rejectedPlans: [
     <candidate plan1>,
   ]
}
```

Starting in MongoDB 8.0, the existing `queryHash` field is duplicated in a new field named `planCacheShapeHash`. If you're using an earlier MongoDB version, you'll only see the `queryHash` field. Future MongoDB versions will remove the deprecated `queryHash` field, and you'll need to use the `planCacheShapeHash` field instead.

Contains information on the selection of the query plan by the [query optimizer.](https://www.mongodb.com/docs/manual/core/query-plans.md#std-label-read-operations-query-optimization)

A string that specifies the [namespace](https://www.mongodb.com/docs/manual/reference/glossary.md#std-term-namespace) with the names of the database and the collection accessed by the query. The namespace has the format `<database>.<collection>`.

A boolean that specifies whether MongoDB applied an [index filter](https://www.mongodb.com/docs/manual/core/query-plans.md#std-label-index-filters) for the [plan cache query shape.](https://www.mongodb.com/docs/manual/reference/glossary.md#std-term-plan-cache-query-shape)

If query settings are set, `querySettings` contains details about the query settings that are applied to the query shape.

To add query settings and explore examples, which include `explain()` output with `querySettings`, see [`setQuerySettings`.](https://www.mongodb.com/docs/manual/reference/command/setquerysettings.md#mongodb-dbcommand-dbcmd.setQuerySettings)

**New in version 8.0**

Starting in MongoDB 8.0, the existing `queryHash` field is duplicated in a new field named `planCacheShapeHash`. If you're using an earlier MongoDB version, you'll only see the `queryHash` field. Future MongoDB versions will remove the deprecated `queryHash` field, and you'll need to use the `planCacheShapeHash` field instead.

A hexadecimal string that represents the hash of the [plan cache query shape](https://www.mongodb.com/docs/manual/reference/glossary.md#std-term-plan-cache-query-shape) and is dependent only on the plan cache query shapes. `planCacheShapeHash` can help identify slow queries (including the query filter of write operations) with the same plan cache query shape.

**Note:**

As with any hash function, two different plan cache query shapes may result in the same hash value. However, the occurrence of hash collisions between different plan cache query shapes is unlikely.

For more information on `planCacheShapeHash` and `planCacheKey`, see [planCacheShapeHash and planCacheKey.](https://www.mongodb.com/docs/manual/core/query-plans.md#std-label-query-hash-plan-cache-key)

A hash of the key for the plan cache entry associated with the query.

Unlike the [`explain.queryPlanner.planCacheShapeHash`](https://www.mongodb.com/docs/manual/reference/explain-results.md#mongodb-data-explain.queryPlanner.planCacheShapeHash), the [`explain.queryPlanner.planCacheKey`](https://www.mongodb.com/docs/manual/reference/explain-results.md#mongodb-data-explain.queryPlanner.planCacheKey) is a function of both the plan cache query shape and the currently available indexes for that shape. Specifically, if indexes that can support the query shape are added or dropped, the `planCacheKey` value may change but the `planCacheShapeHash` value wouldn't change.

For more information on `planCacheShapeHash` and `planCacheKey`, see [planCacheShapeHash and planCacheKey.](https://www.mongodb.com/docs/manual/core/query-plans.md#std-label-query-hash-plan-cache-key)

Time in milliseconds the query planner spent on query optimization. This result doesn't include time spent optimizing inner [`$lookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup.md#mongodb-pipeline-pipe.-lookup) queries.

A boolean that indicates that the entire aggregation pipeline operation was optimized away, and instead, fulfilled by a tree of query plan execution stages.

For example, the following aggregation operation can be fulfilled by the tree of query plan execution rather than using the aggregation pipeline.

```javascript
db.example.aggregate([ { $match: { someFlag: true } } ] )
```

The field is only present if the value is `true` and only applies to explain on aggregation pipeline operations. When `true`, because the pipeline was optimized away, no aggregation stage information appears in the output.

A document that details the plan selected by the [query optimizer.](https://www.mongodb.com/docs/manual/core/query-plans.md)

A string that denotes the name of the stage.

Each stage consists of information specific to the stage. For example, an `IXSCAN` stage includes the index bounds along with other data specific to the index scan. If a stage has a child stage or multiple child stages, the stage will have an `inputStage` or `inputStages`.

This field appears if the operation used the classic query execution engine.

If `stage` is set to `"EOF"`, `type` is a string that denotes the reason for the EOF stage:

- `"nonExistentNamespace"`: indicates the query namespace does not exist.

- `"predicateEvalsToFalse"`: indicates that expression simplification determines that the query will not match any documents.

A document that describes the child stage, which provides the documents or index keys to its parent. The field is present *if* the parent stage has only one child.

An array of documents describing the child stages. Child stages provide the documents or index keys to the parent stage. The field is present *if* the parent stage has multiple child nodes. For example, stages for [$or expressions](https://www.mongodb.com/docs/manual/reference/explain-results.md#std-label-explain-output-or-expression) might consume input from multiple sources.

This field appears if the operation used the classic query execution engine.

A boolean that indicates if the winningPlan is in the plan cache.

This field is `true` for a maximum of one plan between the winning plan and the rejected plans. If the query has no cached plan, the field is `false` for the winning plan and the rejected plans.

Float that represents the estimated abstract cost units used to execute the cost-based ranker per stage. The cost-based ranker chooses the plan with the lowest top level `costEstimate`.

**New in version 8.3.3**

Float that represents the estimated number of documents or keys produced by the stage of the cost-based ranker.

**New in version 8.3.3**

Float that represents the estimated number of index keys that the query planner predicts the plan to process.

A significant difference between the `numKeysEstimate` and the `costEstimate` can indicate issues with the `winningPlan`.

**New in version 8.3.3**

Float that represents the estimated number of documents scanned.

**New in version 8.3.3**

Contains metadata about how the estimate was derived.

**New in version 8.3.3**

The cardinality estimation method (CE) used for this stage. Possible float values include:

- `sampling`: MongoDB calculates the estimate over a sample of the base collection.

- `heuristics`: Uses a set of rules to determine selectivity. Only used when sampling fails.

- `mixed`: The estimate is a result of some computation that mixes estimates of different types.

- `metadata`: The estimate comes from database metadata like collection cardinality.

- `code`: C++ computes the estimate directly, for instance a constant or expression.

**New in version 8.3.3**

A document that details the plan selected by the [query optimizer](https://www.mongodb.com/docs/manual/core/query-plans.md). MongoDB presents the plan as a tree of stages.

This document appears if the query used the [slot-based execution query engine.](https://www.mongodb.com/docs/manual/reference/sbe.md#std-label-sbe-landing)

**New in version 5.1**

A string that denotes the name of the stage.

Each stage consists of information specific to the stage. For example, an `IXSCAN` stage includes the index bounds along with other data specific to the index scan.

If `stage` is set to `"EOF"`, `type` is a string that denotes the reason for the EOF stage:

- `"nonExistentNamespace"`: indicates the query namespace does not exist.

- `"predicateEvalsToFalse"`: indicates that expression simplification determines that the query will not match any documents.

Unique integer field that identifies each stage in the execution plan. Field is included in all stages throughout the `explain` results.

**New in version 5.1**

See [`explain.queryPlanner.winningPlan.inputStage`.](https://www.mongodb.com/docs/manual/reference/explain-results.md#mongodb-data-explain.queryPlanner.winningPlan.inputStage)

Document with information about the slot-based query execution plan tree and stages. **For internal use by MongoDB.**

**New in version 5.1**

String that includes information on each stage in the slot-based query execution plan, including execution order, operations, and slot assignments. **For internal use by MongoDB.**

Starting in MongoDB 8.0, if a query uses [block processing](https://www.mongodb.com/docs/manual/core/timeseries/timeseries-querying.md#std-label-timeseries-querying-block-processing), `block_to_row` and `ts_bucket_to_cellblock` appear in the `stages` output.

**Changed in version 8.0**

Array of candidate plans considered and rejected by the query optimizer. The array can be empty if there were no other candidate plans.

Rejected plans have the same fields as `explain.queryPlanner.winningPlan`.

Starting in MongoDB 8.0, rejected query plans only contain the `find` portion of the query. In previous versions, rejected plans can contain aggregation stages like [`$group`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group). Those aggregation stages aren't used by the query planner to choose the winning plan, so the `rejectedPlans` field only contains the portion of the query that was used to choose the winning plan.

### `executionStats`

The returned [`explain.executionStats`](https://www.mongodb.com/docs/manual/reference/explain-results.md#mongodb-data-explain.executionStats) information details the execution of the winning plan. To include `executionStats` in the results, you must run the explain in either:

- [executionStats](https://www.mongodb.com/docs/manual/reference/method/db.collection.explain.md#std-label-explain-method-executionStats) or

- [allPlansExecution](https://www.mongodb.com/docs/manual/reference/method/db.collection.explain.md#std-label-explain-method-allPlansExecution) verbosity mode. Use `allPlansExecution` mode to include partial execution data captured during [plan selection.](https://www.mongodb.com/docs/manual/core/query-plans.md#std-label-query-plans-query-optimization)

These examples may combine the output structures of the classic and slot-based execution engines. They are not meant to be representative. Your output may differ significantly.

### Unsharded Collections

For unsharded collections, `explain` returns the following `executionStats` information:

```javascript
executionStats: {
   executionSuccess: <boolean>,
   nReturned: <int>,
   executionTimeMillis: <int>,
   totalKeysExamined: <int>,
   totalDocsExamined: <int>,
   executionStages: {
      stage: <STAGE1>
      nReturned: <int>,
      executionTimeMillisEstimate: <int>,
      opens: <int>, // Starting in MongoDB 5.1
      closes: <int>, // Starting in MongoDB 5.1
      works: <int>,
      advanced: <int>,
      needTime: <int>,
      needYield: <int>,
      saveState: <int>,
      restoreState: <int>,
      isEOF: <boolean>,
      ...
      inputStage: {
         stage: <STAGE2>,
         nReturned: <int>,
         ...
         numReads: <int>, // Starting in MongoDB 5.1
         ...
         executionTimeMillisEstimate: <int>,
         ...
         spills: <long long>,
         spilledBytes: <long long>,
         spilledRecords: <long long>,
         spilledDataStorageSize: <long long>,
         peakTrackedMemBytes: <long>, // Starting in 8.3
         ...
         inputStage: {
            ...
         }
      }
   },
   allPlansExecution: [
      {
         nReturned: <int>,
         executionTimeMillisEstimate: <int>,
         totalKeysExamined: <int>,
         totalDocsExamined: <int>,
         score: <double>,
         executionStages: {
            stage: <STAGEA>,
            nReturned: <int>,
            executionTimeMillisEstimate: <int>,
            ...
            inputStage: {
               stage: <STAGEB>,
               ...
               inputStage: {
                 ...
               }
            }
         }
      },
      ...
   ]
   operationMetrics: {
      cpuNanos: <int>,
      cursorSeeks: <int>,
      docBytesRead: <int>,
      docBytesWritten: <int>,
      docUnitsRead: <int>,
      docUnitsReturned: <int>,
      docUnitsWritten: <int>,
      idxEntryBytesRead: <int>,
      idxEntryBytesWritten: <int>,
      idxEntryUnitsRead: <int>,
      idxEntryUnitsWritten: <int>,
      totalUnitsWritten: <int>,
      keysSorted: <int>,
      sorterSpills: <int>
   }
},
...
peakTrackedMemBytes: <long>, // Starting in 8.3
...
```

Contains statistics that describe the completed query execution for the winning plan. For write operations, completed query execution refers to the modifications that *would* be performed, but does *not* apply the modifications to the database.

Number of documents returned by the winning query plan. [`nReturned`](https://www.mongodb.com/docs/manual/reference/explain-results.md#mongodb-data-explain.executionStats.nReturned) corresponds to the `n` field returned by `cursor.explain()` in earlier versions of MongoDB.

Total time in milliseconds required for query plan selection and query execution. It includes the time it takes to run the trial phase part of the plan selection process, but does not include the network time to transmit the data back to the client.

The time reported by `explain.executionStats.executionTimeMillis` is not necessarily representative of actual query time. During steady state operations (when the query plan is cached), or when using [`cursor.hint()`](https://www.mongodb.com/docs/manual/reference/method/cursor.hint.md#mongodb-method-cursor.hint) with `cursor.explain()`, MongoDB bypasses the plan selection process, resulting in a faster actual time, leading to a lower `explain.executionStats.executionTimeMillis` value.

**New in version 8.3**

Maximum number of bytes of tracked memory in use by the current query operation.

The explain execution statistics provide the peak memory for the entire query and also for each blocking stage. If there is only one blocking stage, the query and stage `peakTrackedMemBytes` values are the same.

Number of index entries scanned. [`explain.executionStats.totalKeysExamined`](https://www.mongodb.com/docs/manual/reference/explain-results.md#mongodb-data-explain.executionStats.totalKeysExamined) corresponds to the `nscanned` field returned by `cursor.explain()` in earlier versions of MongoDB.

Number of documents examined during query execution. Common query execution stages that examine documents are `COLLSCAN` and `FETCH`.

**Note:**

[`explain.executionStats.totalDocsExamined`](https://www.mongodb.com/docs/manual/reference/explain-results.md#mongodb-data-explain.executionStats.totalDocsExamined) refers to the total number of documents examined and *not* to the number of documents returned. For example, a stage can examine a document in order to apply a filter. If the document is filtered out, then it has been examined but will not be returned as part of the query result set.

If a document is examined multiple times during query execution, [`explain.executionStats.totalDocsExamined`](https://www.mongodb.com/docs/manual/reference/explain-results.md#mongodb-data-explain.executionStats.totalDocsExamined) counts each examination. That is, [`explain.executionStats.totalDocsExamined`](https://www.mongodb.com/docs/manual/reference/explain-results.md#mongodb-data-explain.executionStats.totalDocsExamined) is *not* a count of the total number of *unique* documents examined.

Double that represents the score of the winning plan chosen by the multi-planner.

**New in version 8.3.3**

Details the completed execution of the winning plan as a tree of stages; i.e. a stage can have an `inputStage` or multiple `inputStages`.

Starting in MongoDB 5.1, a stage can have these input stages:

- `thenStage`

- `elseStage`

- `innerStage`

- `outerStage`

Each stage consists of execution information specific to the stage.

The estimated amount of time in milliseconds for query execution.

Starting in MongoDB 5.1, the number of times a stage was opened during query execution.

Starting in MongoDB 5.1, the number of times a stage was closed during query execution.

Specifies the number of "work units" performed by the query execution stage. Query execution divides its work into small units. A "work unit" might consist of examining a single index key, fetching a single document from the collection, applying a projection to a single document, or doing a piece of internal bookkeeping.

This field appears if the operation used the classic query execution engine.

The number of times that the query stage suspended processing and saved its current execution state, for example in preparation for yielding its locks.

The number of times that the query stage restored a saved execution state, for example after recovering locks that it had previously yielded.

Specifies whether the execution stage has reached end of stream:

- If `true` or `1`, the execution stage has reached end-of-stream.

- If `false` or `0`, the stage may still have results to return. For example, consider a query with a limit whose execution stages consists of a `LIMIT` stage with an input stage of `IXSCAN` for the query. If the query returns more than the specified limit, the `LIMIT` stage will report `isEOF: 1`, but its underlying `IXSCAN` stage will report `isEOF: 0`.

For operations on time series collections, the type of operation.

For operations on time series collections, the filter used to reduce the number of buckets queried in the bucket catalog.

For operations on time series collections, the filter used to query the bucket catalog.

For operations on time series collections, the number of buckets unpacked to resolve the operation.

For operations on time series collections, the number of documents deleted.

For operations on time series collections, the number of documents inserted.

For operations on time series collections, the number of documents matched.

For operations on time series collections, the number of documents modified.

For operations on time series collections, the number of documents upserted.

Each `inputStage` can have different fields depending on the value of `inputStage.stage`. The following table describes possible fields and what stages they can appear in.

Each `inputStage` can have another `inputStage` as a field. See [Explain Output Structure.](https://www.mongodb.com/docs/manual/reference/explain-results.md#std-label-explain-output-structure)

| Field | Description | Applicable Stages |
| --- | --- | --- |
| `docsExamined` | Specifies the number of documents scanned during the query execution stage. | `COLLSCAN`, `FETCH` |
| `keysExamined` | For query execution stages that scan an index `keysExamined` is the total number of in-bounds and out-of-bounds keys that are examined in the process of the index scan. If the index scan consists of a single contiguous range of keys, only in-bounds keys need to be examined. If the index bounds consists of several key ranges, the index scan execution process may examine out-of-bounds keys in order to skip from the end of one range to the beginning of the next. | `IXSCAN` |
| `numReads` | The number of documents scanned or index keys examined during the query execution stage. **New in version 5.1** | `COLLSCAN`, `IXSCAN` |
| `seeks` | The number of times that we had to seek the index cursor to a new position in order to complete the index scan. | `IXSCAN` |
| `usedDisk` | Whether the stage wrote to disk. **New in version 5.3** | `GROUP` |
| `spills` | The number of times the stage spilled to disk. **New in version 8.2** | `GROUP`, `SORT` |
| `spilledBytes` | The total amount of data written to disk in bytes. **New in version 8.2** | `GROUP`, `SORT` |
| `spilledRecords` | The total number of individual records spilled to disk. **New in version 8.2** | `GROUP`, `SORT` |
| `spilledDataStorageSize` | The total disk space, in bytes, used by the spilled data. **New in version 8.2** | `GROUP`, `SORT` |
| `peakTrackedMemBytes` | **New in version 8.3** Maximum number of bytes of tracked memory in use by the current query operation. Starting in MongoDB 9.0, the `COUNT_SCAN`, `GEO_NEAR_2D`, `GEO_NEAR_2DSPHERE`, and `UPDATE` stages also report this field. | `COUNT_SCAN`, `GEO_NEAR_2D`, `GEO_NEAR_2DSPHERE`, `GROUP`, `SORT`, `UPDATE` |

Contains *partial* execution information captured during the [plan selection phase](https://www.mongodb.com/docs/manual/core/query-plans.md#std-label-query-plans-query-optimization) for both the winning and rejected plans. The field is present only if `explain` runs in `allPlansExecution` verbosity mode.

Contains resource consumption statistics, as long as they are not zero. The field is present only if `explain` runs in `executionStats` verbosity mode or higher and if `profileOperationResourceConsumptionMetrics` is enabled.

**Warning:**

MongoDB 8.2 removes `profileOperationResourceConsumptionMetrics`. Therefore, code depending on [operationMetrics](https://www.mongodb.com/docs/manual/reference/explain-results.md#std-label-executionStats) does not work.

### `serverInfo`

### Unsharded Collections

For unsharded collections, `explain` returns the following `serverInfo` information for the MongoDB instance:

```javascript
serverInfo: {
   host: <string>,
   port: <int>,
   version: <string>,
   gitVersion: <string>
}
```

## Execution Plan Statistics for Query with `$lookup` Pipeline Stage

**New in version 5.0**

The [explain results](https://www.mongodb.com/docs/manual/reference/explain-results.md#std-label-explain-results) can include execution statistics for queries that use a [`$lookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup.md#mongodb-pipeline-pipe.-lookup) pipeline stage. To include those execution statistics, you must run the explain operation in one of these execution verbosity modes:

- [executionStats](https://www.mongodb.com/docs/manual/reference/method/db.collection.explain.md#std-label-explain-method-executionStats)

- [allPlansExecution](https://www.mongodb.com/docs/manual/reference/method/db.collection.explain.md#std-label-explain-method-allPlansExecution)

The following fields are included in the explain results for a [`$lookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup.md#mongodb-pipeline-pipe.-lookup) query:

```none
'$lookup': {
   from: <string>,
   as: <string>,
   localField: <string>,
   foreignField: <string>
},
totalDocsExamined: <long>,
totalKeysExamined: <long>,
collectionScans: <long>,
indexesUsed: [ <string_1>, <string_2>, ..., <string_n> ],
executionTimeMillisEstimate: <long>
```

To see the descriptions for the fields in the `$lookup` section, see the [`$lookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup.md#mongodb-pipeline-pipe.-lookup) page.

The other fields are:

Number of documents examined during the query execution.

Number of index keys examined.

Number of times a collection scan occurred during query execution. During a collection scan, each document in a collection is compared to the query predicate. Collection scans occur if no appropriate [index](https://www.mongodb.com/docs/manual/indexes.md#std-label-indexes) exists that [covers](https://www.mongodb.com/docs/manual/core/query-optimization.md#std-label-indexes-covered-queries) the query.

Array of strings with the names of the indexes used by the query.

Estimated time in milliseconds for the query execution.

## Execution Plan Statistics for Search Queries

**New in version 8.1**

The explain results includes [execution statistics](https://www.mongodb.com/docs/manual/reference/explain-results.md#std-label-executionStats) for queries that use a [`$search`](https://www.mongodb.com/docs/search/query/aggregation-stages/search.md#mongodb-pipeline-pipe.-search), [`$searchMeta`](https://www.mongodb.com/docs/search/query/aggregation-stages/searchMeta.md#mongodb-pipeline-pipe.-searchMeta), or [`$vectorSearch`](https://www.mongodb.com/docs/vector-search/query/aggregation-stages/vector-search-stage.md#mongodb-pipeline-pipe.-vectorSearch) pipeline stage. To include execution statistics for search queries, run the `explain` command in one of the following execution verbosity modes:

- [executionStats](https://www.mongodb.com/docs/manual/reference/method/db.collection.explain.md#std-label-explain-method-executionStats)

- [allPlansExecution](https://www.mongodb.com/docs/manual/reference/method/db.collection.explain.md#std-label-explain-method-allPlansExecution)

MongoDB returns execution statistics for search and vector search queries that use the classic engine only.

For more details on search and vector search query explain results, see:

- [Explain Search Results](https://www.mongodb.com/docs/search/query/explain.md#std-label-explain-ref)

- [Explain MongoDB Vector Search Results](https://www.mongodb.com/docs/vector-search/query/explain.md#std-label-avs-explain-ref)

## Collection Scan

If the query planner selects a collection scan, the explain result includes a `COLLSCAN` stage.

If the query planner selects an index, the explain result includes a `IXSCAN` stage. The stage includes information such as the index key pattern, direction of traversal, and index bounds.

Starting in MongoDB 5.3, if the query planner selects a [clustered index](https://www.mongodb.com/docs/manual/reference/method/db.createcollection.md#std-label-db.createCollection.clusteredIndex) for a [clustered collection](https://www.mongodb.com/docs/manual/core/clustered-collections.md#std-label-clustered-collections) and the query contains bounds that define the portion of the index to search, the explain result includes a `CLUSTERED_IXSCAN` stage. The stage includes information about the clustered index key and index bounds.

If the query planner selects a [clustered index](https://www.mongodb.com/docs/manual/reference/method/db.createcollection.md#std-label-db.createCollection.clusteredIndex) for a [clustered collection](https://www.mongodb.com/docs/manual/core/clustered-collections.md#std-label-clustered-collections) and the query *does not* contain bounds, the query performs an unbounded collection scan and the explain result includes a `COLLSCAN` stage.

**Note:**

The [`notablescan`](https://www.mongodb.com/docs/manual/reference/parameters.md#mongodb-parameter-param.notablescan) parameter does not allow unbounded queries that use a clustered index because the queries require a full collection scan.

For more information on execution statistics of collection scans, see [Interpret Explain Plan Results.](https://www.mongodb.com/docs/manual/tutorial/analyze-query-plan.md)

## Covered Queries

When an index [covers](https://www.mongodb.com/docs/manual/core/query-optimization.md#std-label-indexes-covered-queries) a query, MongoDB can both match the query conditions **and** return the results using only the index keys. MongoDB does not need to examine documents from the collection to perform any part of the query.

When an index covers a query, the explain result has an `IXSCAN` stage that is **not** a descendant of a `FETCH` stage.

## `$or` Expression

If MongoDB uses indexes for an [`$or`](https://www.mongodb.com/docs/manual/reference/operator/query/or.md#mongodb-query-op.-or) expression, the result will include the `OR` stage with an [`explain.queryPlanner.winningPlan.inputStages`](https://www.mongodb.com/docs/manual/reference/explain-results.md#mongodb-data-explain.queryPlanner.winningPlan.inputStages) array that details the indexes; e.g.:

```javascript
{
   stage: 'OR',
   inputStages: [
      {
         stage: 'IXSCAN',
         ...
      },
      {
         stage : 'IXSCAN',
         ...
      },
      ...
   ]
}
```

In previous versions of MongoDB, `cursor.explain()` returned the `clauses` array that detailed the indexes.

## Aggregation Explain Output

When you run `explain` on an aggregation, the output contains a top-level `stages` array instead of a single query plan tree. The first entry in the array is normally `$cursor`, which contains the data-access portion of the pipeline. The `$cursor` entry holds the same [`queryPlanner`](https://www.mongodb.com/docs/manual/reference/explain-results.md#std-label-queryPlanner) and [`executionStats`](https://www.mongodb.com/docs/manual/reference/explain-results.md#std-label-executionStats) objects that `find` explain output returns. Entries that follow `$cursor` run in the aggregation framework.

### Stages Absorbed into `$cursor`

The `stages` array often does not match the stages in your pipeline. During optimization, MongoDB moves some pipeline work into the query system, which can use an index to complete that work more efficiently. For example, MongoDB can perform the following optimizations:

- Leading [`$match`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/match.md#mongodb-pipeline-pipe.-match), [`$sort`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sort.md#mongodb-pipeline-pipe.-sort), and [`$limit`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/limit.md#mongodb-pipeline-pipe.-limit) stages are absorbed into `$cursor`. An absorbed [`$match`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/match.md#mongodb-pipeline-pipe.-match) appears as a `filter` in the query plan, and an absorbed [`$limit`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/limit.md#mongodb-pipeline-pipe.-limit) appears as a `LIMIT` stage.

- [`$group`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group) and [`$lookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup.md#mongodb-pipeline-pipe.-lookup) can be pushed into the query plan as `GROUP` and `EQ_LOOKUP` stages. To learn more, see [`$group` Optimization](https://www.mongodb.com/docs/manual/core/aggregation-pipeline-optimization.md#std-label-agg-group-optimization-sbe) and [`$lookup` Optimization.](https://www.mongodb.com/docs/manual/core/aggregation-pipeline-optimization.md#std-label-agg-lookup-optimization-sbe)

- If an index provides the requested sort order, no separate [`$sort`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sort.md#mongodb-pipeline-pipe.-sort) entry appears.

- [`$project`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/project.md#mongodb-pipeline-pipe.-project) and other stages can also be pushed into the query plan, depending on the MongoDB version and the query engine in use.

This list is not exhaustive. Which stages MongoDB absorbs or pushes down can change between releases. For general information on how MongoDB reshapes a pipeline before execution, see [Aggregation Pipeline Optimization.](https://www.mongodb.com/docs/manual/core/aggregation-pipeline-optimization.md#std-label-agg-pipeline-optimization)

As a result, the `stages` array can contain fewer entries than the pipeline you ran. To see which stages the server ran, compare the `stages` array to the `command.pipeline` field in the same output.

### Example

The following aggregation has three pipeline stages:

```javascript
db.comments.aggregate(
     [
        { $match: { date: { $gte: ISODate("2015-01-01") } } },
        { $group: { _id: "$movie_id", commentCount: { $sum: 1 } } },
        { $sort: { commentCount: -1 } }
     ],
     { explain: true }
)

```

The output contains only two entries in the `stages` array:

```javascript
{
  explainVersion: '2',
  stages: [
    {
      '$cursor': {
        queryPlanner: {
          namespace: 'sample_mflix.comments',
          parsedQuery: { date: { '$gte': ISODate('2015-01-01T00:00:00.000Z') } },
          ...
          winningPlan: {
            isCached: false,
            queryPlan: {
              stage: 'GROUP',
              planNodeId: 3,
              inputStage: {
                stage: 'COLLSCAN',
                planNodeId: 1,
                filter: {
                  date: { '$gte': ISODate('2015-01-01T00:00:00.000Z') }
                },
                direction: 'forward'
              }
            },
            ...
          },
          rejectedPlans: []
        },
        ...
      },
      nReturned: Long('697'),
      executionTimeMillisEstimate: Long('31')
    },
    {
      '$sort': { sortKey: { commentCount: -1 } },
      totalDataSizeSortedBytesEstimate: Long('170765'),
      usedDisk: false,
      spills: Long('0'),
      spilledDataStorageSize: Long('0'),
      nReturned: Long('697'),
      executionTimeMillisEstimate: Long('31')
    }
  ],
  ...
}
```

The output shows the following:

- The [`$match`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/match.md#mongodb-pipeline-pipe.-match) stage is absorbed into `$cursor` as the `filter` on the `COLLSCAN` stage.

- The [`$group`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group) stage is pushed into the query plan as the `GROUP` stage.

- The [`$sort`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sort.md#mongodb-pipeline-pipe.-sort) stage remains outside of `$cursor`, which means the pipeline performs an in-memory sort. The entry includes the `usedDisk` and `spills` fields described in [Aggregation Stages with Spill Metrics.](https://www.mongodb.com/docs/manual/reference/explain-results.md#std-label-sort-and-group-executionStats-and-above)

### Pipelines That Are Optimized Away

If the query system can run every stage in the pipeline, the `stages` array does not appear in the output. Instead, the output contains the `explain.queryPlanner.optimizedPipeline` field set to `true` and no aggregation stage information.

## Aggregation Stages with Spill Metrics

When `explain` is run in either [executionStats](https://www.mongodb.com/docs/manual/reference/method/db.collection.explain.md#std-label-explain-method-executionStats) or [allPlansExecution](https://www.mongodb.com/docs/manual/reference/method/db.collection.explain.md#std-label-explain-method-allPlansExecution) verbosity mode, certain aggregation stages that may spill to disk have additional output. These stages include [`$sort`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sort.md#mongodb-pipeline-pipe.-sort), [`$group`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group), [`$setWindowFields`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/setwindowfields.md#mongodb-pipeline-pipe.-setWindowFields), [`$bucketAuto`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucketauto.md#mongodb-pipeline-pipe.-bucketAuto), [`$graphLookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/graphlookup.md#mongodb-pipeline-pipe.-graphLookup), and [`$lookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup.md#mongodb-pipeline-pipe.-lookup) (when using the slot-based execution engine). Starting in MongoDB 8.1, this also includes [`$text`](https://www.mongodb.com/docs/manual/reference/operator/query/text.md#mongodb-query-op.-text) queries that use the `TextOr` execution stage.

**New in version 8.1**

| Stage | Field | Type | Description |
| --- | --- | --- | --- |
| [`$sort`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sort.md#mongodb-pipeline-pipe.-sort) | `totalDataSizeSorted` | long | An estimated number of bytes processed in the [`$sort`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sort.md#mongodb-pipeline-pipe.-sort) stage. |
| [`$sort`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sort.md#mongodb-pipeline-pipe.-sort), [`$group`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group), [`$setWindowFields`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/setwindowfields.md#mongodb-pipeline-pipe.-setWindowFields), [`$bucketAuto`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucketauto.md#mongodb-pipeline-pipe.-bucketAuto), [`$graphLookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/graphlookup.md#mongodb-pipeline-pipe.-graphLookup), [`$lookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup.md#mongodb-pipeline-pipe.-lookup) (SBE only), [`$text`](https://www.mongodb.com/docs/manual/reference/operator/query/text.md#mongodb-query-op.-text) (`TextOr` stage) | `usedDisk` | boolean | Whether the stage wrote to disk. |
| [`$sort`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sort.md#mongodb-pipeline-pipe.-sort), [`$group`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group), [`$setWindowFields`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/setwindowfields.md#mongodb-pipeline-pipe.-setWindowFields), [`$bucketAuto`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucketauto.md#mongodb-pipeline-pipe.-bucketAuto), [`$graphLookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/graphlookup.md#mongodb-pipeline-pipe.-graphLookup), [`$lookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup.md#mongodb-pipeline-pipe.-lookup) (SBE only), [`$text`](https://www.mongodb.com/docs/manual/reference/operator/query/text.md#mongodb-query-op.-text) (`TextOr` stage) | `spills` | long long | The number of times the stage spilled to disk. |
| [`$sort`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sort.md#mongodb-pipeline-pipe.-sort), [`$group`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group), [`$setWindowFields`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/setwindowfields.md#mongodb-pipeline-pipe.-setWindowFields), [`$bucketAuto`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucketauto.md#mongodb-pipeline-pipe.-bucketAuto), [`$graphLookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/graphlookup.md#mongodb-pipeline-pipe.-graphLookup), [`$lookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup.md#mongodb-pipeline-pipe.-lookup) (SBE only), [`$text`](https://www.mongodb.com/docs/manual/reference/operator/query/text.md#mongodb-query-op.-text) (`TextOr` stage) | `spilledBytes` | long long | An estimate of the number of bytes written to disk before compression. |
| [`$sort`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sort.md#mongodb-pipeline-pipe.-sort), [`$group`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group), [`$setWindowFields`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/setwindowfields.md#mongodb-pipeline-pipe.-setWindowFields), [`$bucketAuto`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucketauto.md#mongodb-pipeline-pipe.-bucketAuto), [`$graphLookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/graphlookup.md#mongodb-pipeline-pipe.-graphLookup), [`$lookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup.md#mongodb-pipeline-pipe.-lookup) (SBE only) | `spilledRecords` | long long | The total number of individual records spilled to disk. |
| [`$sort`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sort.md#mongodb-pipeline-pipe.-sort), [`$group`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group), [`$setWindowFields`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/setwindowfields.md#mongodb-pipeline-pipe.-setWindowFields), [`$bucketAuto`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucketauto.md#mongodb-pipeline-pipe.-bucketAuto), [`$graphLookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/graphlookup.md#mongodb-pipeline-pipe.-graphLookup), [`$lookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup.md#mongodb-pipeline-pipe.-lookup) (SBE only), [`$text`](https://www.mongodb.com/docs/manual/reference/operator/query/text.md#mongodb-query-op.-text) (`TextOr` stage) | `spilledDataStorageSize` | long long | The total disk space, in bytes, used by the spilled data. |
| [`$sort`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sort.md#mongodb-pipeline-pipe.-sort), [`$group`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group.md#mongodb-pipeline-pipe.-group), [`$setWindowFields`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/setwindowfields.md#mongodb-pipeline-pipe.-setWindowFields), [`$bucketAuto`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucketauto.md#mongodb-pipeline-pipe.-bucketAuto), [`$graphLookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/graphlookup.md#mongodb-pipeline-pipe.-graphLookup), [`$lookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup.md#mongodb-pipeline-pipe.-lookup) (SBE only) | `peakTrackedMemBytes` | long long | The peak memory usage, in bytes, tracked during stage execution. |

## Aggregation Stages with Expression Memory Tracking

Starting in MongoDB 9.0, when you run `explain` in a mimumum of [executionStats](https://www.mongodb.com/docs/manual/reference/method/db.collection.explain.md#std-label-explain-method-executionStats) verbosity mode, aggregation stages that use the classic query execution engine output a `expressionEvaluationPeakMemoryBytes` field. This field contains the peak memory usage, in bytes, from expression evaluation during stage execution.

**New in version 9.0**

The following stages report `expressionEvaluationPeakMemoryBytes`:

- [`$addFields`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/addfields.md#mongodb-pipeline-pipe.-addFields)

- [`$bucketAuto`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/bucketauto.md#mongodb-pipeline-pipe.-bucketAuto)

- [`$graphLookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/graphlookup.md#mongodb-pipeline-pipe.-graphLookup)

- [`$lookup`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup.md#mongodb-pipeline-pipe.-lookup)

- [`$match`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/match.md#mongodb-pipeline-pipe.-match)

- [`$project`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/project.md#mongodb-pipeline-pipe.-project)

- [`$replaceRoot`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/replaceroot.md#mongodb-pipeline-pipe.-replaceRoot)

- [`$replaceWith`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/replacewith.md#mongodb-pipeline-pipe.-replaceWith)

- [`$set`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/set.md#mongodb-pipeline-pipe.-set)

- [`$unset`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/unset.md#mongodb-pipeline-pipe.-unset)

To learn how MongoDB limits memory usage during aggregation, see [Per-Operation Memory Limit.](https://www.mongodb.com/docs/manual/core/aggregation-pipeline-limits.md#std-label-operation-memory-limit)

## Sort Stage

If MongoDB cannot use an index or indexes to obtain the sort order, the results include a `SORT` stage indicating an in-memory sort operation. If the explain plan does not contain an explicit `SORT` stage, then MongoDB used an index to obtain the sort order.

In aggregation explain output, an in-memory sort can appear as a [`$sort`](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sort.md#mongodb-pipeline-pipe.-sort) entry in the top-level `stages` array instead of a `SORT` stage in the query plan. A pipeline can perform an in-memory sort even though the query plan contains no `SORT` stage. To learn more, see [Aggregation Explain Output.](https://www.mongodb.com/docs/manual/reference/explain-results.md#std-label-explain-output-aggregation)

## Query Shape Hash

Starting in MongoDB 8.0, `explain` outputs the following field:

A hexadecimal string that represents the hash of the [query shape](https://www.mongodb.com/docs/manual/reference/glossary.md#std-term-query-shape). For more information, see [Query Shapes.](https://www.mongodb.com/docs/manual/core/query-shapes.md#std-label-query-shapes)

**New in version 8.0**

## Query Knobs

**New in version 9.0**

Starting in MongoDB 9.0, `explain` outputs the following field:

A document that shows the effective value of each query knob and where the value comes from.

Each field has the form `{ "value": <value>, "source": <string> }`. When you set a query knob with the [`setQuerySettings`](https://www.mongodb.com/docs/manual/reference/command/setquerysettings.md#mongodb-dbcommand-dbcmd.setQuerySettings) command, MongoDB sets the `source` value to `"querySettings"`. When you set a query knob with [`setParameter`](https://www.mongodb.com/docs/manual/reference/command/setparameter.md#mongodb-dbcommand-dbcmd.setParameter), MongoDB sets the `source` value to `"setParameter"`.

Query knobs set through query settings always appear, even if their value equals the default. However, `explain` output omits query knobs that you have not explicitly set.

To learn more, see [Query Knobs.](https://www.mongodb.com/docs/manual/reference/command/setquerysettings.md#std-label-setQuerySettings-query-knobs)
