Overview
In this guide, you can learn how to create MongoDB indexes by using your Django models. Indexes can improve the efficiency of queries and provide additional query and document storage functionality.
Without indexes, MongoDB must scan every document in a collection to find the documents that match a 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 inspects.
Django provides the Index class, which you can use to create an
index on your model. Django MongoDB Backend creates the same index on your
MongoDB collection that the model represents.
Tip
To learn more about the Index class, see Index
in the Django documentation.
Sample Data
The examples in this guide use the Recipe model, which contains an
embedded Nutrition model as the value of its nutrition field.
These model classes have the following definitions:
from django.db import models from django.db.models import Q, F from django_mongodb_backend.models import EmbeddedModel from django_mongodb_backend.fields import EmbeddedModelField, ArrayField from django_mongodb_backend.indexes import SearchIndex, VectorSearchIndex class Nutrition(EmbeddedModel): calories = models.IntegerField(default=0) carb_grams = models.IntegerField(default=0) protein_grams = models.IntegerField(default=0) class Recipe(models.Model): title = models.CharField(max_length=200) cuisine = models.CharField(max_length=200) cook_time = models.IntegerField(default=0) allergens = ArrayField(models.CharField(max_length=100), null=True, blank=True) ratings = ArrayField(models.IntegerField(default=0), size=10) nutrition = EmbeddedModelField(Nutrition, null=True, blank=True) class Meta: db_table = "recipes" def __str__(self): return self.title
In the Recipe model's Meta class, the db_table = "recipes" option
instructs Django MongoDB Backend to map the Recipe model to a MongoDB collection
called recipes. To learn how to create a Django application that
uses models to interact with MongoDB collections, visit the
Get Started tutorial.
Create an Index
To create an index on your model, specify the indexes option
in your model's Meta class. Set the value of this indexes option
to a list of the indexes you want to create, as shown in the following
code:
class Meta: indexes = [ models.Index(<first index definition>), models.Index(<second index definition>), # add more indexes here ]
To define your index, pass the following arguments to the models.Index() method:
fields: Specifies a list of fields to index. This argument is required.name: Specifies the index name. This argument is optional, and Django automatically creates an index name if you don't provide one.condition: Specifies a subset of documents to index. This argument is optional. To learn more about theconditionargument, see the Partial Indexes section of this guide.
After you apply your database migrations, Django MongoDB Backend creates the same indexes on the MongoDB collection.
Tip
To learn how to create and apply database migrations, see Migrations in the Django documentation.
This section shows how to create the following index types:
Single Field Index
Single field indexes store information from a single field in a collection.
By default, all MongoDB collections have an index on the _id field.
The following example updates the Recipe model's Meta class to create
a single field index on the title field, which Django MongoDB Backend creates
on the recipes collection:
class Meta: db_table = "recipes" indexes = [ models.Index(fields=["title"], name="title_idx"), ]
Alternatively, you can set the db_index option on your model's title field
to create the index, as shown in the following code:
class Recipe(models.Model): title = models.CharField(max_length=200, db_index=True)
Compound Index
Compound indexes collect and sort data from multiple fields in a collection. MongoDB groups data by the first field specified in the index, and then by each subsequent field.
The following example updates the Recipe model's Meta class to create
a compound index on the title and cook_time fields, which Django MongoDB Backend creates
on the recipes collection:
class Meta: db_table = "recipes" indexes = [ models.Index(fields=["title", "cook_time"]), ]
Multikey Index
Multikey indexes collect and sort data from array fields. When you create an index on an array field, MongoDB automatically sets that index as a multikey index.
The following example updates the Recipe model's Meta class to create
a compound index on the allergens array field, which Django MongoDB Backend creates
on the recipes collection:
class Meta: db_table = "recipes" indexes = [ models.Index(fields=["allergens"], name="allergy_idx"), ]
Embedded Document Index
You can create indexes on fields that store embedded model values, which MongoDB represents as embedded documents.
The following example updates the Recipe model's Meta class to create
an index on the nutrition embedded model field, which Django MongoDB Backend creates
on the recipes collection:
class Meta: db_table = "recipes" indexes = [ models.Index(fields=["nutrition"]), ]
Important
The index created in the preceding example is only used in queries that
specify the entire embedded document. Queries on a specific field within
the embedded document do not use the index. However, you can index
fields within the embedded document by adding an inner Meta class
to the Nutrition model and specifying the indexes option.
Advanced Index Configuration
This section shows how to create the following advanced index types:
Warning
Search Index Migrations
After you create a new MongoDB Search or Vector Search Index and run the database migration commands, Django might take some time to apply the migrations. To ensure data consistency, Django blocks until MongoDB completes the index operation. The migrations can take seconds or minutes to complete, depending on the size of your collection.
Search Indexes
MongoDB Search indexes specify the behavior of a MongoDB Search query, which is a full-text search on your MongoDB collections.
To create a Search index, assign the indexes option in your model's
Meta class to a SearchIndex object. Pass the following arguments to the
SearchIndex() constructor in any order:
fields: The fields you want to index.name: (Optional) The name of your Search index. If you do not specify this argument, Django automatically generates an index name.
Starting in Django MongoDB Backend v5.2.2, you can also pass the following arguments to
SearchIndex():
field_mappings: (Optional) A dictionary that maps field names to index options. You can use this argument instead offieldsto create a complex search index that specifies index behavior for individual fields.analyzer: (Optional) The analyzer to apply to string fields while indexing. If you do not specify this argument, MongoDB Server defaults tolucene.standard.search_analyzer: (Optional) The analyzer to apply to query text. If you do not specify this argument, its value is the same as youranalyzervalue. If you omit both arguments, MongoDB Server defaults tolucene.standard.
Tip
To learn more about MongoDB Search queries and indexes, see the following resources:
Search Index Reference in the Atlas documentation
Search analyzers in the Atlas documentation
SearchIndex class in the Django MongoDB Backend API documentation
Basic Search Index Example
The following example updates the Recipe model's Meta class to create
a basic Search index named "title_search_idx" on the title field:
class Meta: db_table = "recipes" indexes = [ SearchIndex( fields=["title"], name="title_search_idx", ) ]
Advanced Search Index Example
The following example creates a Search index that indexes the
cuisine field as the token type and sets the analyzer to lucene.simple:
class Meta: db_table = "recipes" indexes = [ SearchIndex( name="cuisine_search_idx", field_mappings={ "cuisine": { "type": "token" } }, analyzer="lucene.simple" ) ]
Tip
To learn more about the Search index configuration in the preceding example, see the following resources from the Atlas documentation:
Vector Search Indexes
MongoDB Vector Search indexes allow you to query data based on its semantic meaning rather than by keyword matches. You can integrate vector search with full-text search queries and AI frameworks to support a range of use cases.
To create a vector search index, assign the indexes option in your model's
Meta class to a VectorSearchIndex object. Pass the following arguments to the
VectorSearchIndex() constructor in any order:
name: (Optional) The name of your Vector Search index. If you do not specify this argument, Django automatically generates an index name.fields: The fields you want to index. At least one must be a vector field, represented by an array ofFloatFieldorIntegerFieldvalues with a size.similarities: The similarity function to use. You can use the"cosine","dotProduct", or"euclidean"similarity function. Specify the function as a single string value or a list of values that assigns functions to individual vector fields.
The following example updates the Recipe model's Meta class to create
a vector search index named "vector_search_idx" on the ratings vector field
and the cook_time numeric field:
class Meta: db_table = "recipes" indexes = [ VectorSearchIndex( name=["vector_search_idx"], fields=["ratings", "cook_time"], similarities=["cosine", "euclidean"], ) ]
Tip
To learn more about Vector Search queries and indexes, see the following resources:
Vector Search in the Atlas documentation.
VectorSearchIndex class in the Django MongoDB Backend API documentation.
Partial Indexes
Partial indexes index only the documents in a collection that meet specified filter criteria, which reduces storage use and performance costs.
To create a partial index, pass the condition argument to the models.Index()
method. Set the condition value to a Q object that includes the filter
criteria. When using the condition argument, you must also pass the name
argument to models.Index().
Tip
To learn more about Q objects, see Q
in the Django documentation.
The following example updates the Recipe model's Meta class to create
a partial index on the cuisine field, instructing Django MongoDB Backend to
only index documents that have a cook_time value less than 30:
class Meta: db_table = "recipes" indexes = [ models.Index(fields=["cuisine"], condition=Q(cook_time__lt=30), name="fast_cuisine_idx"), ]
Unique Indexes
Unique indexes allow you to prevent indexed fields from storing duplicate values. On a single field, unique indexes ensure that a value appears at most once for the specified field. On multiple fields, unique indexes ensure that any given combination of the index key values appears at most once.
Single Field Example
The following example updates the Recipe model's cuisine field,
setting the unique option to True to create a unique single field index:
cuisine = models.CharField(max_length=200, unique=True)
Note
Setting the unique option to True automatically creates
an index on the given field.
Compound Example
The following example updates the Recipe model's Meta class to create
a compound index on the title and cuisine fields. The code
sets the constraints option to a UniqueConstraint instance, which
creates a unique compound index on these fields:
class Meta: db_table = "recipes" constraints = [ models.UniqueConstraint(fields=["title", "cuisine"], name="unique_regional_meal"), ]
Tip
Setting the constraints option to a UniqueConstraint automatically
creates an index on the specified fields. To learn more about the Meta
class's constraint option, see Constraints
in the Django documentation.
Additional Information
To learn more about the index types mentioned in this guide, see the following MongoDB Server manual resources:
To learn more about creating indexes on Django models, see
Index in the Django
documentation.