Docs Menu

Perform Raw Database Queries

In this guide, you can learn how to use Django MongoDB Backend to run raw queries on your MongoDB database. Raw queries allow you to query the database by using MongoDB's aggregation pipeline syntax rather than Django methods. You can also run queries directly on your MongoClient object for expanded access to your MongoDB data.

The Django QuerySet API provides a raw() method, which allows you to perform raw SQL queries on relational databases. However, Django MongoDB Backend does not support the raw() method. Instead, the ODM provides the raw_aggregate() method, which you can use to send instructions to the database in pipeline stages.

Note

Django provides a QuerySet.aggregate() method, which differs from the QuerySet.raw_aggregate() method. You can use aggregate() to retrieve values by aggregating a collection of model objects. To learn more about the aggregate() method, see aggregate in the Django documentation.

You can run database queries by calling QuerySet methods on your model's Manager. The Manager class handles database operations and allows you to interact with your MongoDB data by referencing Django models. By default, Django adds a Manager named objects to every model class. This default Manager does not support the raw_aggregate() method. To use this MongoDB-specific method, set your model's objects field to a custom manager called MongoManager.

The examples in this guide use the Movie and Theater models, which represent collections in the sample_mflix database from the Atlas sample datasets. These models explicitly set the objects field to use a custom MongoManager, rather than Django's default Manager class. The model classes have the following definitions:

from django.db import models
from django_mongodb_backend.fields import ArrayField
from django_mongodb_backend.managers import MongoManager
class Movie(models.Model):
title = models.CharField(max_length=200)
plot = models.TextField(blank=True)
runtime = models.IntegerField(default=0)
released = models.DateTimeField("release date", null=True, blank=True)
genres = ArrayField(models.CharField(max_length=100), null=True, blank=True)
objects = MongoManager()
class Meta:
db_table = "movies"
managed = False
def __str__(self):
return self.title
class Theater(models.Model):
theaterId = models.IntegerField(default=0)
objects = MongoManager()
class Meta:
db_table = "theaters"
managed = False
def __str__(self):
return self.theaterId

The Movie and Theater models include an inner Meta class, which specifies model metadata, and a __str__() method, which defines the model's string representation. To learn about these model features, see Define a Model in the Create Models guide.

You can use the Python interactive shell to run the code examples. To enter the shell, run the following command from your project's root directory:

python manage.py shell

After entering the Python shell, ensure that you import the following models and modules:

from <your application name>.models import Movie, Theater
from django.utils import timezone
from datetime import datetime

To learn how to create a Django application that uses the Movie model and the Python interactive shell to interact with MongoDB documents, visit the Get Started with Django MongoDB Backend tutorial.

To run a raw database query, pass an aggregation pipeline to the raw_aggregate() method. Aggregation pipelines contain one or more stages that provide instructions on how to process documents. After calling the raw_aggregate() method, Django MongoDB Backend passes your pipeline to the pymongo.collection.Collection.aggregate() method and returns the query results as model objects.

Tip

To learn more about constructing aggregation pipelines, see Aggregation Pipeline in the MongoDB Server manual.

This section shows how to use the raw_aggregate() method to perform the following tasks:

This example runs a raw database query by calling the raw_aggregate() method on your Movie model's MongoManager, which queries the sample_mflix.movies collection. The code passes the following aggregation pipeline stages to raw_aggregate():

  • $match: Filters for documents that have a title field value of "The Parent Trap"

  • $project: Includes the title and released fields of the returned model objects

movies = Movie.objects.raw_aggregate([
{"$match": {"title": "The Parent Trap"}},
{"$project": {
"title": 1,
"released": 1
}
}])
for m in movies:
print(f"Plot of {m.title}, released on {m.released}: {m.plot}\n")
Plot of The Parent Trap, released on 1961-06-21 00:00:00+00:00:
Teenage twin girls swap places and scheme to reunite their divorced parents.
Plot of The Parent Trap, released on 1998-07-29 00:00:00+00:00:
Identical twins, separated at birth and each raised by one of their
biological parents, discover each other for the first time at summer
camp and make a plan to bring their wayward parents back together.

Note

The raw_aggregate() method returns deferred model instances, which means that you can load fields omitted by the $project stage on demand. In the preceding example, the query retrieves the title and released fields. The print statement runs a separate query to retrieve the plot field.

You can run Atlas Search queries on your database to perform fine-grained text searches. These queries provide advanced search functionality, such as matching text phrases, scoring results for relevance, and highlighting matches.

To specify an Atlas Search query, create an Atlas Search index that covers the fields you want to query. Then, pass a $search or $searchMeta stage in an aggregation pipeline parameter to the raw_aggregate() method.

Important

You cannot use the QuerySet API to create Atlas Search indexes. However, you can create an index by exposing your MongoClient object directly, on which you can call the PyMongo driver's create_search_index() method. To learn how to expose the MongoClient, see the MongoClient Operations section of this guide.

For instructions on using the PyMongo driver to create an Atlas Search index, see Atlas Search and Vector Search Indexes in the PyMongo documentation.

This example runs an Atlas Search query by passing the $search pipeline stage to the raw_aggregate() method. The code performs the following actions:

  • Specifies the Atlas Search index that covers the plot field

  • Queries for documents whose plot values contain the string "whirlwind romance" with no more than 3 words between them

  • Returns portions of the plot string values that match the query and metadata that indicates where the matches occurred

  • Includes the title field and the highlight, or matching text, of each result

movies = Movie.objects.raw_aggregate([
{
"$search": {
"index": "<search-index-name>",
"phrase": {
"path": "plot",
"query": "whirlwind romance",
"slop": 3
},
"highlight": {
"path": "plot"
}
}
},
{
"$project": {
"title": 1,
"highlight": {"$meta": "searchHighlights"}
}
}
])
for m in movies:
print(f"Title: {m.title}, text match details: {m.highlight}\n")
Title: Tokyo Fiancèe, text match details: [{'score': 2.3079638481140137, 'path': 'plot',
'texts': [{'value': 'A young Japanophile Belgian woman in Tokyo falls into a ', 'type': 'text'},
{'value': 'whirlwind', 'type': 'hit'}, {'value': ' ', 'type': 'text'}, {'value': 'romance',
'type': 'hit'}, {'value': ' with a Francophile Japanese student.', 'type': 'text'}]}]
Title: Designing Woman, text match details: [{'score': 2.3041324615478516, 'path': 'plot',
'texts': [{'value': 'A sportswriter and a fashion-designer marry after a ', 'type': 'text'},
{'value': 'whirlwind', 'type': 'hit'}, {'value': ' ', 'type': 'text'}, {'value': 'romance',
'type': 'hit'}, {'value': ', and discover they have little in common.', 'type': 'text'}]}]
Title: Vivacious Lady, text match details: [{'score': 2.220963478088379, 'path': 'plot',
'texts': [{'value': 'On a quick trip to the city, young university professor Peter Morgan
falls in love with nightclub performer Francey Brent and marries her after a ', 'type': 'text'},
{'value': 'whirlwind', 'type': 'hit'}, {'value': ' ', 'type': 'text'}, {'value': 'romance',
'type': 'hit'}, {'value': '. ', 'type': 'text'}]}]
Title: Ek Hasina Thi, text match details: [{'score': 3.11773419380188, 'path': 'plot', 'texts':
[{'value': 'The ', 'type': 'text'}, {'value': 'whirlwind', 'type': 'hit'}, {'value': ' ', 'type':
'text'}, {'value': 'romance', 'type': 'hit'}, {'value': ' turns sour when she is framed for his
underworld crimes. ', 'type': 'text'}]}]
Title: Kick, text match details: [{'score': 2.00649356842041, 'path': 'plot', 'texts': [{'value':
'An adrenaline junkie walks away from a ', 'type': 'text'}, {'value': 'whirlwind', 'type': 'hit'},
{'value': ' ', 'type': 'text'}, {'value': 'romance', 'type': 'hit'}, {'value': ' and embraces a new
life as a thief, though he soon finds himself pursued by veteran police officer and engaged in a turf
war with a local gangster.', 'type': 'text'}]}]
Title: A Tale of Winter, text match details: [{'score': 3.3978850841522217, 'path': 'plot', 'texts':
[{'value': 'Felicie and Charles have a serious if ', 'type': 'text'}, {'value': 'whirlwind', 'type':
'hit'}, {'value': ' holiday ', 'type': 'text'}, {'value': 'romance', 'type': 'hit'}, {'value': '. ',
'type': 'text'}]}]

Important

When running the preceding example, ensure that you replace the <search-index-name> placeholder with the name of your Atlas Search index that covers the plot field.

You can use the raw_aggregate() method to run queries on fields containing geospatial data. Geospatial data represents a geographic location on the surface of the Earth or on a Euclidean plane.

To run a geospatial query, create a 2d or 2dsphere index on fields containing geospatial data. Then, pass one of the following query operators in an aggregation pipeline parameter to the raw_aggregate() method:

  • $near

  • $geoWithin

  • $nearSphere

  • $geoIntersects

Important

You cannot use the QuerySet API to create 2d or 2dsphere indexes. However, you can create indexes by exposing your MongoClient object directly, on which you can call the PyMongo driver's create_index() method. To learn how to expose the MongoClient, see the MongoClient Operations section of this guide.

For instructions on using the PyMongo driver to create geospatial indexes, see Geospatial Indexes in the PyMongo documentation.

This example runs a geospatial query by passing the $match and $geoWithin pipeline stages to the raw_aggregate() method. The code performs the following actions:

  • Specifies a list of coordinates that represent Chicago's boundaries

  • Queries for documents in which the location.geo field stores a location within the Chicago area

  • Retrieves and prints the theaterId values of each movie theater in Chicago

chicago_bounds = {
"type": "Polygon",
"coordinates": [[
[-87.851, 41.976],
[-87.851, 41.653],
[-87.651, 41.653],
[-87.651, 41.976],
[-87.851, 41.976]
]]
}
theaters = Theater.objects.raw_aggregate([
{
"$match": {
"location.geo": {
"$geoWithin": {
"$geometry": chicago_bounds
}
}
}
},
{
"$project": {
"theaterId": 1
}
}
])
for t in theaters:
print(f"Theater ID: {t.theaterId}")
Theater ID: 2447
Theater ID: 311
Theater ID: 320
Theater ID: 2960
Theater ID: 2741
Theater ID: 306
Theater ID: 322
Theater ID: 319
Theater ID: 2862
Theater ID: 1777
Theater ID: 814
Theater ID: 323

If you want to run database operations that neither the QuerySet API nor the raw_aggregate() method provide, you can operate on your MongoClient directly. When working with the MongoClient, you can can access the PyMongo driver's database operations. Use the following syntax to expose the MongoClient:

from django.db import connections
client = connections["<DATABASES key>"].database.client

Replace the "<DATABASES key>" placeholder with the key in your DATABASES dictionary that corresponds to your target database. To use your default database, replace the placeholder with "default".

Tip

To learn how to use PyMongo to interact with MongoDB data, see the PyMongo documentation.

To view more examples that use the raw_aggregate() method, see QuerySet API Reference in the Django MongoDB Backend API documentation.

To learn more about running aggregation operations, see Aggregation Operations in the MongoDB Server manual.

To learn more about Atlas Search, see Atlas Search in the Atlas documentation.

To learn more about running geospatial queries, see Geospatial Queries in the MongoDB Server manual.