Hashed indexes maintain entries with hashes of the values of the indexed field.
Hashed indexes support sharding using hashed shard keys. Hashed based sharding uses a hashed index of a field as the shard key to partition data across your sharded cluster.
Using a hashed shard key to shard a collection results in a more even distribution of data. See Hashed Sharding for more details.
Hashing Function
Hashed indexes use a hashing function to compute the hash of the value of the index field. [1] The hashing function collapses embedded documents and computes the hash for the entire value but does not support multi-key (i.e. arrays) indexes. Specifically, creating a hashed index on a field that contains an array or attempting to insert an array into a hashed indexed field returns an error.
Tip
MongoDB automatically computes the hashes when resolving queries using hashed indexes. Applications do not need to compute hashes.
| [1] | Starting in version 4.0, the mongo shell provides the
method convertShardKeyToHashed(). This method uses the
same hashing function as the hashed index and can be used to see
what the hashed value would be for a key. |
Create a Hashed Index
To create a hashed index, specify
hashed as the value of the index key, as in the following
example:
db.collection.createIndex( { _id: "hashed" } )
Create a Compound Hashed Index
New in version 4.4.
Starting with MongoDB 4.4, MongoDB supports creating compound indexes
that include a single hashed field. To create a compound hashed index,
specify hashed as the value of any single index key when creating
the index:
db.collection.createIndex( { "fieldA" : 1, "fieldB" : "hashed", "fieldC" : -1 } )
Compound hashed indexes require featureCompatibilityVersion set to 4.4.
Considerations
Embedded Documents
The hashing function collapses embedded documents and computes the hash for the entire value, but does not support multi-key (i.e. arrays) indexes. Specifically, creating a hashed index on a field that contains an array or attempting to insert an array to a hashed indexed field returns an error.
Unique Constraint
MongoDB does not support specifying a unique constraint on a hashed
index. You can instead create an additional non-hashed index with the
unique constraint on that field. MongoDB can use that non-hashed index
for enforcing uniqueness on the field.
2 53 Limit
Warning
MongoDB hashed indexes truncate floating point numbers to 64-bit integers
before hashing. For example, a hashed index would store the same
value for a field that held a value of 2.3, 2.2, and 2.9.
To prevent collisions, do not use a hashed index for floating
point numbers that cannot be reliably converted to 64-bit
integers (and then back to floating point). MongoDB hashed indexes do
not support floating point values larger than 2 53.
To see what the hashed value would be for a key, see
convertShardKeyToHashed().
PowerPC and 2 63
For hashed indexes, MongoDB 4.2 ensures that the hashed value for the floating point value 2 63 on PowerPC is consistent with other platforms.
Although hashed indexes on a field that may contain floating point values greater than 2 53 is an unsupported configuration, clients may still insert documents where the indexed field has the value 2 63.
To list all hashed indexes for all
collections in your deployment, you can use the following
operation in the mongo shell:
db.adminCommand("listDatabases").databases.forEach(function(d){ let mdb = db.getSiblingDB(d.name); mdb.getCollectionInfos({ type: "collection" }).forEach(function(c){ let currentCollection = mdb.getCollection(c.name); currentCollection.getIndexes().forEach(function(idx){ let idxValues = Object.values(Object.assign({}, idx.key)); if (idxValues.includes("hashed")) { print("Hashed index: " + idx.name + " on " + d.name + "." + c.name); printjson(idx); }; }); }); });
To check if the indexed field contains the value 2 63, run the following operation for the collection and the indexed field:
If the indexed field type is a scalar and never a document:
// substitute the actual collection name for <collection> // substitute the actual indexed field name for <indexfield> db.<collection>.find( { <indexfield>: Math.pow(2,63) } ); If the indexed field type is a document (or a scalar), you can run:
// substitute the actual collection name for <collection> // substitute the actual indexed field name for <indexfield> db.<collection>.find({ $where: function() { function findVal(obj, val) { if (obj === val) return true; for (const child in obj) { if (findVal(obj[child], val)) { return true; } } return false; } return findVal(this.<indexfield>, Math.pow(2, 63)); } })