How hideIndex() Works in MongoDB

MongoDB introduced the db.collection.hideIndex() method in MongoDB 4.4.

This method hides an existing index from the query planner. This allows you to evaluate the potential impact of dropping an index without actually dropping the index.

If hiding it has a negative impact, you can use db.collection.unhideIndex() to unhide the index. This saves you from having to drop the index, then recreate it.

Example

Suppose we have a collection called pets. Let’s return the current indexes on that collection.

db.pets.getIndexes()

Result:

[
	{
		"v" : 2,
		"key" : {
			"_id" : 1
		},
		"name" : "_id_"
	},
	{
		"v" : 2,
		"key" : {
			"name" : 1,
			"type" : -1
		},
		"name" : "idx_name_1_type_-1"
	},
	{
		"v" : 2,
		"key" : {
			"weight" : -1
		},
		"name" : "idx_weight_-1"
	}
]

We can see that it has three indexes. Let’s choose the third one called idx_weight_-1 for our example.

First, let’s see what the query plan looks like when we run queries that use that index.

db.pets.find( { weight: { $gt: 10 } } ).explain()

Here, we’re searching for pets that are over a certain weight. We’re using the explain() method to display the query plan instead of the actual results.

Here’s what the query plan looks like for this query:

{
	"queryPlanner" : {
		"plannerVersion" : 1,
		"namespace" : "PetHouse.pets",
		"indexFilterSet" : false,
		"parsedQuery" : {
			"weight" : {
				"$gt" : 10
			}
		},
		"queryHash" : "CEB852E7",
		"planCacheKey" : "851FBDB5",
		"winningPlan" : {
			"stage" : "FETCH",
			"inputStage" : {
				"stage" : "IXSCAN",
				"keyPattern" : {
					"weight" : -1
				},
				"indexName" : "idx_weight_-1",
				"isMultiKey" : false,
				"multiKeyPaths" : {
					"weight" : [ ]
				},
				"isUnique" : false,
				"isSparse" : false,
				"isPartial" : false,
				"indexVersion" : 2,
				"direction" : "forward",
				"indexBounds" : {
					"weight" : [
						"[inf.0, 10.0)"
					]
				}
			}
		},
		"rejectedPlans" : [ ]
	},
	"ok" : 1
}

We can see that it uses IXSCAN which means that it used the index.

Now let’s hide the index.

Hide the Index

This is where hideIndex() comes in. We can use it to hide the index so that it doesn’t show up on the query plan like it did in the previous example.

db.pets.hideIndex("idx_weight_-1")

Output:

{ "hidden_old" : false, "hidden_new" : true, "ok" : 1 }

The output of the hideIndex() method displays the old value for the hidden field (in this case false) and the new value (in this case true).

However, if we hide an already hidden index (or unhide an already unhidden one), these aren’t displayed, and we just get the following:

{ "ok" : 1 }

In any case, the index is now hidden.

Re-Check the Query Plan

Let’s re-run the previous query to see what the query plan looks like now.

db.pets.find( { weight: { $gt: 10 } } ).explain()

Result:

{
	"queryPlanner" : {
		"plannerVersion" : 1,
		"namespace" : "PetHouse.pets",
		"indexFilterSet" : false,
		"parsedQuery" : {
			"weight" : {
				"$gt" : 10
			}
		},
		"queryHash" : "CEB852E7",
		"planCacheKey" : "851FBDB5",
		"winningPlan" : {
			"stage" : "COLLSCAN",
			"filter" : {
				"weight" : {
					"$gt" : 10
				}
			},
			"direction" : "forward"
		},
		"rejectedPlans" : [ ]
	},
	"ok" : 1
}

This time we get a COLLSCAN, which means that it didn’t use the index – it did a collection scan.

Check Whether an Index is Hidden

You can use the getIndexes() method to check whether or not an index is hidden.

So, we can run the same query that we ran earlier to return all indexes:

db.pets.getIndexes()

Result:

[
	{
		"v" : 2,
		"key" : {
			"_id" : 1
		},
		"name" : "_id_"
	},
	{
		"v" : 2,
		"key" : {
			"name" : 1,
			"type" : -1
		},
		"name" : "idx_name_1_type_-1"
	},
	{
		"v" : 2,
		"key" : {
			"weight" : -1
		},
		"name" : "idx_weight_-1",
		"hidden" : true
	}
]

Can’t Hide Indexes? Check this Setting.

The mongod featureCompatibilityVersion must be at least 4.4 before you can hide indexes. However, once hidden, an index will remain hidden even with featureCompatibilityVersion set to 4.2 on MongoDB 4.4 binaries.

You can check the featureCompatibilityVersion setting with the following code:

db.adminCommand( 
    { 
        getParameter: 1, 
        featureCompatibilityVersion: 1 
    } 
)

You can set it using the setFeatureCompatibilityVersion command:

db.adminCommand( { setFeatureCompatibilityVersion: "4.4" } )

The setFeatureCompatibilityVersion command needs to be run in the admin database.

Also note, you cannot hide the _id index.