Docs Menu
Docs Home
/ / /
C#/.NET
/

Indexes

On this page

  • Overview
  • Query Coverage and Performance
  • Operational Considerations
  • Index Types
  • Single Field Indexes
  • Compound Indexes
  • Multikey Indexes
  • Clustered Indexes
  • Atlas Search Indexes
  • Text Indexes
  • Geospatial Indexes
  • Unique Indexes
  • Wildcard Indexes
  • List Indexes

In this guide, you can learn how to use indexes with the MongoDB .NET/C# Driver. Indexes can improve the efficiency of queries and add functionality to querying and storing documents.

Without indexes, MongoDB must scan every document in a collection to find the documents that match each query. These collection scans are slow and can negatively affect the performance of your application. However, if an appropriate index exists for a query, MongoDB can use the index to limit the documents it must inspect.

When you execute a query against MongoDB, your query can include various elements:

  • Query criteria that specify fields and values that you are looking for

  • Options that affect the query's execution, such as read concern

  • Projection criteria to specify the fields you want MongoDB to return

  • Sort criteria to specify the order of documents returned from MongoDB

When all the fields specified in the query, projection, and sort are in the same index, MongoDB returns results directly from that index, also called a covered query.

For more information about how to ensure your index covers your query criteria and projection, see the Covered Query section in the MongoDB server manual.

To improve query performance, build indexes on fields that appear often in your application's queries and operations that return sorted results. Each index that you add consumes disk space and memory when active, so it might be necessary to track index memory and disk usage for capacity planning. In addition, when a write operation updates an indexed field, MongoDB also updates the related index.

Since MongoDB supports dynamic schemas, applications can query against fields whose names cannot be known in advance or are arbitrary. MongoDB 4.2 introduced wildcard indexes to help support these queries. Wildcard indexes are not designed to replace workload-based index planning.

For more information about designing your data model and choosing indexes appropriate for your application, see the Server documentation on Indexing Strategies and Data Modeling and Indexes.

MongoDB provides several different index types to support querying your data. The following sections describe the most common index types and provide sample code for creating each index type.

Note

These example uses the sample_mflix.movies and sample_mflix.theaters collections from the Atlas sample datasets. To learn how to create a free MongoDB Atlas cluster and load the sample datasets, see Quick Start.

Single-field indexes are indexes with a reference to a single field within a collection's documents. They improve single field query and sort performance, and support TTL Indexes that automatically remove documents from a collection after a certain amount of time or at a specific clock time.

Note

The _id_ index is an example of a single-field index. This index is automatically created on the _id field when a new collection is created.

The following example creates an index in ascending order on the title field within the sample_mflix.movies collection:

var indexModel = new CreateIndexModel<Movie>(Builders<Movie>.IndexKeys.Ascending(m => m.Title));
collection.Indexes.CreateOne(indexModel);

The following is an example of a query that is covered by the index created in the preceding code snippet:

// Define query parameters
var filter = Builders<Movie>.Filter.Eq(m => m.Title, "Batman");
var sort = Builders<Movie>.Sort.Ascending(m => m.Title);
var projection = Builders<Movie>.Projection.Include(m => m.Title).Exclude(m => m.Id);
// Execute query
var results = collection.Find(filter).Sort(sort).Project(projection);

For more information, see Single Field Indexes in the Server manual.

Compound indexes hold references to multiple fields within a collection's documents, improving query and sort performance.

The following example creates a compound index on the type and rated fields within the sample_mflix.movies collection:

var indexModel = new CreateIndexModel<Movie>(Builders<Movie>.IndexKeys
.Ascending(m => m.Type)
.Ascending(m => m.Rated));
collection.Indexes.CreateOne(indexModel);

The following is an example of a query that is covered by the index created in the preceding code snippet:

// Define query parameters
var typeFilter = Builders<Movie>.Filter.Eq(m => m.Type, "movie");
var ratedFilter = Builders<Movie>.Filter.Eq(m => m.Rated, "G");
var filter = Builders<Movie>.Filter.And(typeFilter, ratedFilter);
var sort = Builders<Movie>.Sort.Ascending(m => m.Type).Ascending(m => m.Rated);
var projection = Builders<Movie>.Projection
.Include(m => m.Type)
.Include(m => m.Rated)
.Exclude(m => m.Id);
// Execute query
var results = collection.Find(filter).Sort(sort).Project(projection);

For more information, see Compound Indexes in the Server manual.

Multikey indexes collect and sort data from fields containing array values. You can define a multikey index using the same syntax as a single field or compound index.

The following example creates a compound, multikey index on the rated, genres (an array of Strings), and title fields within the sample_mflix.movies collection:

var indexModel = new CreateIndexModel<Movie>(Builders<Movie>.IndexKeys
.Ascending(m => m.Rated)
.Ascending(m => m.Genres)
.Ascending(m => m.Title));
collection.Indexes.CreateOne(indexModel);

The following is an example of a query that is covered by the index created in the preceding code snippet:

// Define query parameters
var genreFilter = Builders<Movie>.Filter.AnyEq(m => m.Genres, "Animation");
var ratedFilter = Builders<Movie>.Filter.Eq(m => m.Rated, "G");
var filter = Builders<Movie>.Filter.And(genreFilter, ratedFilter);
var sort = Builders<Movie>.Sort.Ascending(m => m.Title);
var projection = Builders<Movie>.Projection
.Include(m => m.Title)
.Include(m => m.Rated)
.Exclude(m => m.Id);
// Execute query
var results = collection.Find(filter).Sort(sort).Project(projection);

Multikey indexes behave differently from other indexes in terms of query coverage, index bound computation, and sort behavior. To learn more about multikey indexes, including a discussion of their behavior and limitations, see the Multikey Indexes page in the Server manual.

Clustered indexes instruct a collection to store documents ordered by a key value. To create a clustered index, specify the clustered index option with the _id field as the key and the Unique property as true when you create your collection. A collection can only contain a single clustered index. If you want to create a clustered index, then it must be specified when you create a collection.

The following example creates a clustered index on the _id field while creating a new sample_mflix.reviews collection:

var database = mongoClient.GetDatabase("sample_mflix");
var clusteredIndexOptions = new ClusteredIndexOptions<Review>
{
Key = Builders<Review>.IndexKeys.Ascending(r => r.Id),
Unique = true
};
database.CreateCollection("reviews", new CreateCollectionOptions<Review>
{
ClusteredIndex = clusteredIndexOptions
});

To learn more, see Clustered Indexes and Clustered Collections in the Server manual.

The Atlas Search feature enables you to perform full-text searches on collections hosted on MongoDB Atlas. The indexes specify the behavior of the search and which fields to index.

To learn more about MongoDB Atlas Search, see the Atlas Search Indexes documentation.

Note

The Atlas Search Index management methods run asynchronously. The driver methods can return before confirming that they ran successfully. To determine the current status of the indexes, call the IMongoSearchIndexManager.List() method.

The following sections contain links to tutorials that demonstrate how to create and interact with Atlas Search indexes.

Before you can perform a search on an Atlas collection, you must first create an Atlas Search index on the collection. To learn how to create an Atlas Search index using the .NET/C# Driver, see Create an Atlas Search Index in the Atlas manual and select C# from the language dropdown.

To learn how to view a list of your Atlas Search indexes using the .NET/C# Driver, see View an Atlas Search Index in the Atlas manual and select C# from the language dropdown.

To learn how to modify an existing Atlas Search index using the .NET/C# Driver, see Edit an Atlas Search Index in the Atlas manual and select C# from the language dropdown.

To learn how to delete an Atlas Search index using the .NET/C# Driver, see Delete an Atlas Search Index in the Atlas manual and select C# from the language dropdown.

Text indexes support text search queries on string content. These indexes can include any field whose value is a string or an array of string elements. MongoDB supports text search for various languages. You can specify the default language as an option when creating the index.

Tip

MongoDB offers an improved full-text search solution, Atlas Search. To learn more about Atlas Search indexes and how to use them, see the Atlas Search Indexes section of this guide.

Note that text indexes cannot support Atlas Search queries, and Atlas Search indexes cannot support text queries.

The following example creates a text index on the plot field within the sample_mflix.movies collection:

var indexModel = new CreateIndexModel<Movie>(Builders<Movie>.IndexKeys.Text(m => m.Plot));
collection.Indexes.CreateOne(indexModel);

The following query uses the text index created in the preceding code snippet:

// Define query parameters
var filter = Builders<Movie>.Filter.Text("java coffee shop");
var projection = Builders<Movie>.Projection.Include(m => m.Plot).Exclude(m => m.Id);
// Execute query
var results = collection.Find(filter).Project(projection);

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. A text search runs on all the text fields within the compound index.

The following snippet creates a compound text index for the title and genre fields within the sample_mflix.movies collection:

var indexModel = new CreateIndexModel<Movie>(Builders<Movie>.IndexKeys
.Text(m => m.Title)
.Text(m => m.Genre));
collection.Indexes.CreateOne(indexModel);

For more information, see Compound Text Index Restrictions and Text Indexes in the Server manual.

MongoDB supports queries of geospatial coordinate data using 2dsphere indexes. With a 2dsphere index, you can query the geospatial data for inclusion, intersection, and proximity.

To create a 2dsphere index, you must specify a field that contains only GeoJSON objects. For more details about this type, see GeoJSON objects in the MongoDB Server manual.

The location.geo field in the following sample 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 already covered by a geospatial index results in an error.

var indexModel = new CreateIndexModel<Theater>(Builders<Theater>.IndexKeys.Geo2DSphere(t => t.Location.Geo));
collection.Indexes.CreateOne(indexModel);

The following is an example of a geospatial query using the "location.geo" index:

// Stores the coordinates of the NY MongoDB headquarters
var refPoint = GeoJson.Point(GeoJson.Position(-73.98456, 40.7612));
// Creates a filter to match documents that represent locations up to 1000 meters from the specified point directly from the geospatial index
var filter = Builders<Theater>.Filter.Near(m => m.Location.Geo, refPoint, 1000.0, 0.0);
// Execute the query
var results = collection.Find(filter);

MongoDB also supports 2d indexes for calculating distances on a Euclidean plane and for working with the "legacy coordinate pairs" syntax used in MongoDB 2.2 and earlier. To learn more, see Geospatial Queries in the Server manual.

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 fields that you want to prevent duplication on and set the Unique option to true.

The following example creates a unique, descending index on the theaterId field within the sample_mflix.theaters collection.

var options = new CreateIndexOptions { Unique = true };
var indexModel = new CreateIndexModel<Theater>(Builders<Theater>.IndexKeys.Descending(t => t.TheaterId),
options);
collection.Indexes.CreateOne(indexModel);

If you attempt to perform a write operation that stores a duplicate value that violates the unique index, MongoDB will throw an error that resembles the following:

E11000 duplicate key error index

To learn more, see Unique Indexes in the Server manual.

Wildcard indexes enable queries against unknown or arbitrary fields. These indexes can be beneficial if you are using a dynamic schema.

The following example creates an ascending wildcard index on all values of the location field within the sample_mflix.theaters collection, including values nested in subdocuments and arrays:

var indexModel = new CreateIndexModel<Theater>(Builders<Theater>.IndexKeys.Wildcard(t => t.Location));
collection.Indexes.CreateOne(indexModel);

For more information, see the Wildcard Indexes page in the Server manual.

You can use the List() method to retrieve a list of indexes in your collection.

The following example uses the List() method to list all indexes in a collection:

var indexes = collection.Indexes.List();
foreach (var index in indexes.ToList())
{
Console.WriteLine(index);
}

Back

Transactions