Indexes
On this page
- Overview
- Query Coverage and Performance
- Operational Considerations
- Index Types
- Single Field Indexes
- Compound Indexes
- Multikey Indexes (Indexes on Array Fields)
- Atlas Search and Atlas Vector Search Indexes
- Clustered Indexes
- Text Indexes
- Geospatial Indexes
- Unique Indexes
- Remove an Index
- Additional Information
- API Documentation
Overview
In this guide, you can learn how to use indexes in the MongoDB Go Driver.
Indexes support the efficient execution of queries in MongoDB. Without indexes, MongoDB scans every document in a collection (a collection scan) to find documents that match your query. Collection scans are slow and can negatively affect the performance of your application. With an appropriate index, MongoDB limits the number of documents it inspects.
Tip
You can also use indexes in update operations, delete operations, and certain aggregation pipeline stages.
Query Coverage and Performance
A query in MongoDB can contain the following elements:
Element | Necessity | Purpose |
---|---|---|
Query | Required | Specify the fields and values you're looking for. |
Options | Optional | Specify how the query executes. |
Projection | Optional | Specify the fields that MongoDB returns. |
Sort | Optional | Specify the order MongoDB returns documents. |
When you specify these elements in the same index, MongoDB returns results directly from the index, also called a covered query.
Important
Sort Criteria
Your sort criteria must match or invert the order of the index.
Consider an index on the field name
in ascending order (A-Z) and age
in descending order (9-0):
name_1_age_-1
MongoDB uses this index when you sort your data by either:
name
ascending,age
descendingname
descending,age
ascending
Specifying a sort order of name
and age ascending or name and age
descending requires an in-memory sort.
To learn how to ensure your index covers your query criteria and projection, see Query Coverage.
Operational Considerations
To improve your query performance, create indexes on fields that appear often in your queries and operations that return sorted results. Track index memory and disk usage for capacity planning since each index that you add consumes disk space and memory. In addition, when a write operation updates an indexed field, MongoDB also must update the related index.
Since MongoDB supports dynamic schemas, your application can query against fields with unknown or arbitrary names. MongoDB 4.2 introduced wildcard indexes to help support these queries. Wildcard indexes are not designed to replace workload-based index planning.
To learn more about designing your data model and choosing indexes appropriate for your application, see Indexing Strategies and Data Modeling and Indexes.
Index Types
MongoDB supports several index types to support querying your data. The following sections describe and show how to create the most common index types. To view a full list of index types, see Indexes.
Single Field Indexes
Single field indexes holds a reference to a field within a collection's documents.
This index improves single field queries and sort performance, and supports TTL indexes that automatically remove documents from a collection after a certain amount of time.
Note
The _id_
index is an example of a single field index. This index
is automatically created on the _id
field when you create a new
collection.
Example
The following example creates an index in ascending order on the
title
field in the sample_mflix.movies
collection:
coll := client.Database("sample_mflix").Collection("movies") indexModel := mongo.IndexModel{ Keys: bson.D{{"title", 1}}, } name, err := coll.Indexes().CreateOne(context.TODO(), indexModel) if err != nil { panic(err) } fmt.Println("Name of Index Created: " + name)
Name of Index Created: title_1
Compound Indexes
Compound indexes hold a reference to multiple fields within a collection's documents. This index improves query and sort performance.
Example
The following example creates a compound index on the fullplot
and
title
fields in the sample_mflix.movies
collection:
coll := client.Database("sample_mflix").Collection("movies") indexModel := mongo.IndexModel{ Keys: bson.D{ {"fullplot", -1}, {"title", 1} } } name, err := coll.Indexes().CreateOne(context.TODO(), indexModel) if err != nil { panic(err) } fmt.Println("Name of Index Created: " + name)
Name of Index Created: fullplot_-1_title_1
Multikey Indexes (Indexes on Array Fields)
Multikey indexes use the same syntax as a single field index and a compound index. This index improves the performance of queries that specify an array field as an index.
Example
The following example creates a multikey index on the cast
field in the sample_mflix.movies
collection:
coll := client.Database("sample_mflix").Collection("movies") indexModel := mongo.IndexModel{ Keys: bson.D{{"cast", -1}} } name, err := coll.Indexes().CreateOne(context.TODO(), indexModel) if err != nil { panic(err) } fmt.Println("Name of Index Created: " + name)
Name of Index Created: cast_-1
Atlas Search and Atlas Vector Search Indexes
You can programmatically manage your Atlas Search and Atlas Vector Search indexes by using the Go driver.
The Atlas Search feature enables you to perform full-text searches on collections hosted on MongoDB Atlas. To learn more about Atlas Search, see the Atlas Search documentation.
Atlas Vector Search enables you to perform semantic searches on vector embeddings stored in Atlas. To learn more about Atlas Vector Search, see the Atlas Vector Search documentation.
To learn more about how to run Atlas Vector Search queries, see the Run an Atlas Vector Search Query guide.
The following sections contain code examples that demonstrate how to manage Atlas Search and Atlas Vector Search indexes.
Create a Search Index
You can create an Atlas Search or an Atlas Vector Search index by providing
an index definition to the SearchIndexView.CreateOne()
method.
The following example creates an Atlas Search index on the plot
field of the
sample_mflix.movies
collection:
// Sets the index name and type to "search" const indexName = "search_index" opts := options.SearchIndexes().SetName(indexName).SetType("search") // Defines the index definition searchIndexModel := mongo.SearchIndexModel{ Definition: bson.D{ {Key: "mappings", Value: bson.D{ {Key: "dynamic", Value: false}, {Key: "fields", Value: bson.D{ {Key: "plot", Value: bson.D{ {Key: "type", Value: "string"}, }}, }}, }}, }, Options: opts, } // Creates the index searchIndexName, err := coll.SearchIndexes().CreateOne(ctx, searchIndexModel) if err != nil { log.Fatalf("Failed to create the Atlas Search index: %v", err) }
The following example creates an Atlas Vector Search index on the plot_embedding
field in the sample_mflix.embedded_movies
collection:
// Defines the structs used for the index definition type vectorDefinitionField struct { Type string `bson:"type"` Path string `bson:"path"` NumDimensions int `bson:"numDimensions"` Similarity string `bson:"similarity"` Quantization string `bson:"quantization"` } type vectorDefinition struct { Fields []vectorDefinitionField `bson:"fields"` } // Sets the index name and type to "vectorSearch" const indexName = "vector_search_index" opts := options.SearchIndexes().SetName(indexName).SetType("vectorSearch") // Defines the index definition vectorSearchIndexModel := mongo.SearchIndexModel{ Definition: vectorDefinition{ Fields: []vectorDefinitionField{{ Type: "vector", Path: "plot_embedding", NumDimensions: 1536, Similarity: "dotProduct", Quantization: "scalar"}}, }, Options: opts, } // Creates the index searchIndexName, err := coll.SearchIndexes().CreateOne(ctx, vectorSearchIndexModel) if err != nil { log.Fatalf("Failed to create the Atlas Vector Search index: %v", err) }
List a Search Index
You can use the SearchIndexView.List()
method to list an Atlas Search or Atlas
Vector Search index by specifying the name of the index.
The following example lists the details of the specified Atlas Search or Atlas Vector Search index:
// Specifies the index to retrieve const indexName = "myIndex" opts := options.SearchIndexes().SetName(indexName) // Retrieves the details of the specified index cursor, err := coll.SearchIndexes().List(ctx, opts) // Prints the index details to the console as JSON var results []bson.D if err := cursor.All(ctx, &results); err != nil { log.Fatalf("Failed to unmarshal results to bson: %v", err) } res, err := json.Marshal(results) if err != nil { log.Fatalf("Failed to marshal results to json: %v", err) } fmt.Println(res)
Update a Search Index
You can use the SearchIndexView.UpdateOne()
method to update an Atlas Search
or Atlas Vector Search index by specifying the name of the index and the new
index definition.
The following example updates an Atlas Vector Search index by providing the name of the index and a new index definition:
// Specifies the index name and the new index definition const indexName = "vector_search_index" type vectorDefinitionField struct { Type string `bson:"type"` Path string `bson:"path"` NumDimensions int `bson:"numDimensions"` Similarity string `bson:"similarity"` } type vectorDefinition struct { Fields []vectorDefinitionField `bson:"fields"` } definition := vectorDefinition{ Fields: []vectorDefinitionField{ { Type: "vector", Path: "plot_embedding", NumDimensions: 1536, Similarity: "cosine", Quantization: "scalar", }, }, } // Updates the specified index err := coll.SearchIndexes().UpdateOne(ctx, indexName, definition) if err != nil { log.Fatalf("Failed to update the index: %v", err) }
Delete a Search Index
You can use the SearchIndexView.DropOne()
method to delete an Atlas Search or
Atlas Vector Search index by specifying the name of the index.
The following example deletes an Atlas Search or Atlas Vector Search index with the specified name:
// Deletes the specified index err := coll.SearchIndexes().DropOne(ctx, "myIndex") if err != nil { log.Fatalf("Failed to delete the index: %v", err) }
Clustered Indexes
Clustered indexes improve the performance of insert, update, and delete operations on clustered collections. Clustered collections store documents ordered by the clustered index key value.
To create a clustered index, specify the clustered index option with the
_id
field as the key and the unique field as true
when you
create your collection.
Example
The following example creates a clustered index on the _id
field in
the db.tea
collection:
db := client.Database("db") cio := bson.D{{"key", bson.D{{"_id", 1}}}, {"unique", true}} opts := options.CreateCollection().SetClusteredIndex(cio) db.CreateCollection(context.TODO(), "tea", opts)
Text Indexes
Text indexes support text search queries on string content. This index requires a string field or an array of strings. MongoDB supports text search for several languages. You can specify the default language as an option when creating the index.
A collection can only contain one text index. If you want to create a text index for multiple text fields, you must create a compound index. The text search runs on all the text fields within the compound index.
Tip
Text indexes differ from the more powerful Atlas full text search indexes. We recommend Atlas search for Atlas users.
Example
The following example creates a text index on the plot
field with
italian
as the default language in the sample_mflix.movies
collection:
coll := client.Database("sample_mflix").Collection("movies") indexModel := mongo.IndexModel{Keys: bson.D{{"plot", "text"}, {"default_language", "italian"}}} name, err := coll.Indexes().CreateOne(context.TODO(), indexModel) if err != nil { panic(err) } fmt.Println("Name of Index Created: " + name)
Name of Index Created: plot_text
Geospatial Indexes
MongoDB supports queries containing geospatial coordinate data by using
2dsphere indexes. A 2dsphere
index must be in a GeoJSON objects
field.
This index allows you to perform the following:
Query geospatial data for inclusion, intersection, and proximity.
Calculation of distances on a Euclidean plane and for working with the "legacy coordinate pairs" syntax used in MongoDB 2.2 and earlier.
Example
The location.geo
field in a document from the
sample_mflix.theaters
collection is a GeoJSON Point object that
describes the coordinates of the theater:
{ "_id" : ObjectId("59a47286cfa9a3a73e51e75c"), "theaterId" : 104, "location" : { "address" : { "street1" : "5000 W 147th St", "city" : "Hawthorne", "state" : "CA", "zipcode" : "90250" }, "geo" : { "type" : "Point", "coordinates" : [ -118.36559, 33.897167 ] } } }
The following example creates a 2dsphere
index on the location.geo
field:
Important
Attempting to create a geospatial index on a field that is covered by a geospatial index results in an error.
indexModel := mongo.IndexModel{ Keys: bson.D{{"location.geo", "2dsphere"}} } name, err := coll.Indexes().CreateOne(context.TODO(), indexModel) if err != nil { panic(err) } fmt.Println("Name of Index Created: " + name)
location.geo_2dsphere
Unique Indexes
Unique indexes ensure that the indexed fields do not store duplicate
values. By default, MongoDB creates a unique index on the _id
field
during the creation of a collection.
To create a unique index, specify the field or combination of fields
that you want to prevent duplication on and set the unique
option to
true
.
Example
The following example creates a unique, descending index on the theaterId
field:
indexModel := mongo.IndexModel{ Keys: bson.D{{"theaterId", -1}}, Options: options.Index().SetUnique(true), } name, err := coll.Indexes().CreateOne(context.TODO(), indexModel) if err != nil { panic(err) } fmt.Println("Name of Index Created: " + name)
Name of Index Created: theaterId_-1
Remove an Index
You can delete any index from a collection except the default unique index on the
_id
field. To remove an index, pass the name of your index to the
DropOne()
method.
The following example removes an index called title_1
from the sample_mflix.movies
collection:
coll := client.Database("sample_mflix").Collection("movies") err := coll.Indexes().DropOne(context.TODO(), "title_1") if err != nil { panic(err) }
Additional Information
To learn more about the indexes mentioned, see the following guides:
To learn more about the operations mentioned, see the following guides:
API Documentation
To learn more about any of the methods discussed in this guide, see the following API Documentation: