Skip to content

Commit aaaf482

Browse files
committed
DOCSP-46322: Raw queries
1 parent 5babfca commit aaaf482

File tree

3 files changed

+298
-0
lines changed

3 files changed

+298
-0
lines changed

snooty.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ patch-version-number = "{+version-number+}.1" # a
3535
version = "v{+version-number+}"
3636
stable-api = "Stable API"
3737
api-root = "https://pymongo.readthedocs.io/en/{+patch-version-number+}/api/"
38+
django-api = "https://django-mongodb.readthedocs.io/en/latest/"
3839
string-data-type = "``str``"
3940
int-data-type = "``int``"
4041
bool-data-type = "``bool``"

source/interact-data.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
.. _django-interact-data:
2+
3+
==================
4+
Interact with Data
5+
==================
6+
7+
.. facet::
8+
:name: genre
9+
:values: reference
10+
11+
.. meta::
12+
:keywords: odm, crud, query
13+
14+
.. toctree::
15+
:caption: Interact with Data
16+
17+
Perform Raw Queries </interact-data/raw-queries>
Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
.. _django-raw-queries:
2+
3+
============================
4+
Perform Raw Database Queries
5+
============================
6+
7+
.. contents:: On this page
8+
:local:
9+
:backlinks: none
10+
:depth: 2
11+
:class: singlecol
12+
13+
.. facet::
14+
:name: genre
15+
:values: reference
16+
17+
.. meta::
18+
:keywords: number, amount, estimation, code example
19+
20+
Overview
21+
---------
22+
23+
In this guide, you can learn how to use {+django-odm+} to run
24+
raw queries on your MongoDB database. Raw queries allow you to
25+
query the database by using MongoDB's aggregation pipeline syntax
26+
rather than Django methods.
27+
28+
The Django QuerySet API provides a ``QuerySet.raw()`` method, which allows
29+
you to perform raw SQL queries on relational databases. {+django-odm+}
30+
does not support the ``raw()`` method. Instead, the ODM provides the
31+
``QuerySet.raw_aggregate()`` method, which you can use to send commands
32+
to the database in pipeline stages.
33+
34+
Sample Data
35+
~~~~~~~~~~~
36+
37+
The examples in this guide use the ``Movie`` model, which represents the
38+
``sample_mflix.movies`` collection from the :atlas:`Atlas sample datasets </sample-data>`.
39+
The ``Movie`` model class has the following definition:
40+
41+
.. code-block:: python
42+
43+
from django.db import models
44+
from django_mongodb_backend.fields import EmbeddedModelField, ArrayField
45+
from django_mongodb_backend.managers import MongoManager
46+
47+
class Movie(models.Model):
48+
title = models.CharField(max_length=200)
49+
plot = models.TextField(null=True)
50+
runtime = models.IntegerField(default=0)
51+
released = models.DateTimeField("release date", null=True)
52+
awards = EmbeddedModelField(Award)
53+
genres = ArrayField(models.CharField(max_length=100), blank=True)
54+
objects = MongoManager()
55+
56+
class Meta:
57+
db_table = "movies"
58+
59+
def __str__(self):
60+
return self.title
61+
62+
To learn how to create a Django application that uses a similar ``Movie``
63+
model to interact with MongoDB documents, visit the :ref:`django-get-started`
64+
tutorial.
65+
66+
.. _django-raw-queries-run:
67+
68+
Perform a Raw Query
69+
-------------------
70+
71+
To run a raw database query, pass an aggregation pipeline
72+
to the ``QuerySet.raw_aggregate()`` method. Aggregation pipelines
73+
contain one or more stages that provide instructions on how to
74+
process documents. After calling the ``raw_aggregate()`` method,
75+
{+django-odm+} passes your pipeline to the ``pymongo.collection.Collection.aggregate()``
76+
method and returns the query results as model objects.
77+
78+
.. tip::
79+
80+
To learn more about constructing aggregation pipelines, see
81+
:manual:`Aggregation Pipeline </core/aggregation-pipeline/>`
82+
in the {+mdb-server+} manual.
83+
84+
This section shows how to use the ``raw_aggregate()`` method
85+
to perform the following tasks:
86+
87+
- :ref:`django-raw-queries-filter-group`
88+
- :ref:`django-raw-queries-search`
89+
- :ref:`django-raw-queries-geospatial`
90+
91+
.. _django-raw-queries-filter-group:
92+
93+
Filter and Project Document Fields
94+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
95+
96+
This example runs a raw database query by calling the
97+
``raw_aggregate()`` method on your ``Movie`` objects,
98+
which represent documents in the ``sample_mflix.movies`` MongoDB
99+
collection. The code passes the following aggregation pipeline stages
100+
to ``raw_aggregate()``:
101+
102+
- ``$match``: Filters for documents that have a ``title``
103+
field value of ``"The Parent Trap"``
104+
105+
- ``$project``: Includes the ``title`` and ``released`` fields
106+
of the returned model objects
107+
108+
.. io-code-block::
109+
:copyable: true
110+
111+
.. input::
112+
:language: python
113+
114+
from sample_mflix.models import Movie
115+
116+
movies = Movie.objects.raw_aggregate([
117+
{"$match": {"title": "The Parent Trap"}},
118+
{"$project": {
119+
"title": 1,
120+
"released": 1
121+
}
122+
}])
123+
124+
for m in movies:
125+
print(f"Plot of {m.title}, released on {m.released}: {m.plot}\n")
126+
127+
.. output::
128+
:language: javascript
129+
:visible: false
130+
131+
Plot of The Parent Trap, released on 1961-06-21 00:00:00+00:00:
132+
Teenage twin girls swap places and scheme to reunite their divorced parents.
133+
134+
Plot of The Parent Trap, released on 1998-07-29 00:00:00+00:00:
135+
Identical twins, separated at birth and each raised by one of their
136+
biological parents, discover each other for the first time at summer
137+
camp and make a plan to bring their wayward parents back together.
138+
139+
.. note::
140+
141+
The ``raw_aggregate()`` method returns deferred model instances,
142+
which means that you can load fields omitted by the ``$project`` stage
143+
on demand. In the preceding example, the query retrieves the ``title``
144+
and ``released`` fields. The print statement runs a separate query
145+
to retrieve the ``plot`` field.
146+
147+
.. _django-raw-queries-search:
148+
149+
Run an Atlas Search Query
150+
~~~~~~~~~~~~~~~~~~~~~~~~~
151+
152+
You can run Atlas Search queries on your database to perform
153+
fine-grained text searches. These queries provide advanced search
154+
functionality, such as matching text phrases, scoring results for
155+
relevance, and highlighting matches.
156+
157+
To specify an Atlas Search query, create an Atlas Search index
158+
that covers the fields you want to query. Then, specify the ``$search``
159+
or ``$searchMeta`` stage in an aggregation pipeline parameter to
160+
the ``raw_aggregate()`` method.
161+
162+
.. important::
163+
164+
You cannot use {+django-odm+} to create Atlas Search indexes.
165+
166+
For instructions on using the PyMongo driver to create an Atlas
167+
Search index, see :driver:`Atlas Search and Vector Search Indexes
168+
</python/pymongo-driver/current/indexes/atlas-search-index/>` in
169+
the PyMongo documentation.
170+
171+
For instructions on alternative methods of creating search indexes,
172+
see :atlas:`Create an Atlas Search Index </atlas-search/tutorial/create-index/>`
173+
in the Atlas documentation.
174+
175+
This example runs an Atlas Search query by passing the ``$search`` pipeline
176+
stage to the ``raw_aggregate()`` method. The code performs the following
177+
actions:
178+
179+
- Specifies the Atlas Search index that covers the ``plot`` field
180+
- Queries for documents whose ``plot`` values contain the string
181+
``"whirlwind romance"`` with no more than ``3`` words in between
182+
- Returns portions of the ``plot`` string values that match
183+
the query, along with metadata that indicates where the matches
184+
occurred
185+
- Includes the ``title`` field and the ``highlight``, or matching text,
186+
of each result
187+
188+
.. io-code-block::
189+
:copyable: true
190+
191+
.. input::
192+
:language: python
193+
194+
movies = Movie.objects.raw_aggregate([
195+
{
196+
"$search": {
197+
"index": "<search-index-name>",
198+
"phrase": {
199+
"path": "plot",
200+
"query": "whirlwind romance",
201+
"slop": 3
202+
},
203+
"highlight": {
204+
"path": "plot"
205+
}
206+
}
207+
},
208+
{
209+
"$project": {
210+
"title": 1,
211+
"highlight": {"$meta": "searchHighlights"}
212+
}
213+
}
214+
])
215+
216+
for m in movies:
217+
print(f"Title: {m.title}, text match details: {m.highlight}\n")
218+
219+
.. output::
220+
:language: javascript
221+
:visible: false
222+
223+
Title: Tokyo Fiancèe, text match details: [{'score': 2.3079638481140137, 'path': 'plot',
224+
'texts': [{'value': 'A young Japanophile Belgian woman in Tokyo falls into a ', 'type': 'text'},
225+
{'value': 'whirlwind', 'type': 'hit'}, {'value': ' ', 'type': 'text'}, {'value': 'romance',
226+
'type': 'hit'}, {'value': ' with a Francophile Japanese student.', 'type': 'text'}]}]
227+
228+
Title: Designing Woman, text match details: [{'score': 2.3041324615478516, 'path': 'plot',
229+
'texts': [{'value': 'A sportswriter and a fashion-designer marry after a ', 'type': 'text'},
230+
{'value': 'whirlwind', 'type': 'hit'}, {'value': ' ', 'type': 'text'}, {'value': 'romance',
231+
'type': 'hit'}, {'value': ', and discover they have little in common.', 'type': 'text'}]}]
232+
233+
Title: Vivacious Lady, text match details: [{'score': 2.220963478088379, 'path': 'plot',
234+
'texts': [{'value': 'On a quick trip to the city, young university professor Peter Morgan
235+
falls in love with nightclub performer Francey Brent and marries her after a ', 'type': 'text'},
236+
{'value': 'whirlwind', 'type': 'hit'}, {'value': ' ', 'type': 'text'}, {'value': 'romance',
237+
'type': 'hit'}, {'value': '. ', 'type': 'text'}]}]
238+
239+
Title: Ek Hasina Thi, text match details: [{'score': 3.11773419380188, 'path': 'plot', 'texts':
240+
[{'value': 'The ', 'type': 'text'}, {'value': 'whirlwind', 'type': 'hit'}, {'value': ' ', 'type':
241+
'text'}, {'value': 'romance', 'type': 'hit'}, {'value': ' turns sour when she is framed for his
242+
underworld crimes. ', 'type': 'text'}]}]
243+
244+
Title: Kick, text match details: [{'score': 2.00649356842041, 'path': 'plot', 'texts': [{'value':
245+
'An adrenaline junkie walks away from a ', 'type': 'text'}, {'value': 'whirlwind', 'type': 'hit'},
246+
{'value': ' ', 'type': 'text'}, {'value': 'romance', 'type': 'hit'}, {'value': ' and embraces a new
247+
life as a thief, though he soon finds himself pursued by veteran police officer and engaged in a turf
248+
war with a local gangster.', 'type': 'text'}]}]
249+
250+
Title: A Tale of Winter, text match details: [{'score': 3.3978850841522217, 'path': 'plot', 'texts':
251+
[{'value': 'Felicie and Charles have a serious if ', 'type': 'text'}, {'value': 'whirlwind', 'type':
252+
'hit'}, {'value': ' holiday ', 'type': 'text'}, {'value': 'romance', 'type': 'hit'}, {'value': '. ',
253+
'type': 'text'}]}]
254+
255+
.. important::
256+
257+
When running the preceding example, ensure that you replace
258+
the ``<search-index-name>`` placeholder with the name of your
259+
Atlas Search index that covers the ``plot`` field.
260+
261+
.. _django-raw-queries-geospatial:
262+
263+
Query Geospatial Data
264+
~~~~~~~~~~~~~~~~~~~~~
265+
266+
267+
268+
Additional Information
269+
----------------------
270+
271+
To view more examples that use the ``raw_aggregate()`` method,
272+
see `QuerySet API Reference <{+django-api+}querysets.htmln>`__
273+
in the {+django-odm+} API documentation.
274+
275+
To learn more about running aggregation operations, see
276+
:manual:`Aggregation Operations </aggregation/>`
277+
in the {+mdb-server+} manual.
278+
279+
To learn more about Atlas Search, see :atlas:`Atlas Search </atlas-search>`
280+
in the Atlas documentation.

0 commit comments

Comments
 (0)