How unhideIndex() Works in MongoDB

In MongoDB, the db.collection.unhideIndex() method unhides a hidden index.

A hidden index is one that’s hidden from the query planner. When you unhide an index, it is no longer hidden from the query planner, and it’s immediately available for use.

Example

Suppose we have a collection called pets, and we want to check it for hidden indexes. We could run the following query to return all indexes on the 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",
		"hidden" : true
	}
]

We can see that there are three indexes. The third one is hidden. We know that, because it has "hidden" : true.

That index is on the weight field. When we run a query through the query plan that queries the weight field, we’ll see that it doesn’t use the index.

Example:

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
}

We can see that it did a COLLSCAN (a collection scan), which means that it didn’t use the index.

Unhide the Index

We can use the unhideIndex() method to unhide the index. This method accepts the name of the index or its key pattern as a parameter to specify which index to unhide.

Example:

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

Output:

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

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

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

{ "ok" : 1 }

Regardless, the index is now unhidden.

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" : "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 used IXSCAN, which means that it used the index.

Check Whether the Index has been Unhidden

We can use the getIndexes() method again to check whether or not the index has been unhidden.

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 see the same three indexes that we saw in the earlier example, but this time we don’t see "hidden" : true.

But we also don’t see "hidden" : false.

Unhiding an index simply removes the "hidden" : true part from the result of getIndexes(). The hidden option is only available if the value is true. The hidden option is a boolean value, so we can therefore infer that if it’s not "hidden" : true, then it’s "hidden" : false.

Can’t Hide/Unhide 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.