Skip to content

Commit 1332688

Browse files
committed
doc enhancements + simpler test
1 parent 1989ab0 commit 1332688

File tree

2 files changed

+50
-25
lines changed

2 files changed

+50
-25
lines changed

docs/source/querysets.rst

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,46 @@ Some MongoDB-specific ``QuerySet`` methods are available by adding a custom
2424

2525
Similar to :meth:`QuerySet.raw()<django.db.models.query.QuerySet.raw>`, but
2626
instead of a raw SQL query, this method accepts a pipeline that will be passed
27-
to :meth:`pymongo.collection.Collection.aggregate`. The pipeline must return
28-
the necessary fields to construct model instances and may also return
29-
additional fields that will be added as annotations on the models.
27+
to :meth:`pymongo.collection.Collection.aggregate`.
3028

3129
For example, you could write a custom match criteria::
3230

33-
Post.objects.raw_aggregate([{"$match": {"title": "MongoDB is fun!"}}])
31+
Question.objects.raw_aggregate([{"$match": {"question_text": "What's up"}}])
32+
33+
The pipeline may also return additional fields that will be added as
34+
annotations on the models::
35+
36+
>>> questions = Question.objects.raw_aggregate([{
37+
... "$project": {
38+
... "question_text": 1,
39+
... "pub_date": 1,
40+
... "year_published": {"$year": "$pub_date"}
41+
... }
42+
... }])
43+
>>> for q in questions:
44+
... print(f"{q.question_text} was published in {q.year_published}.")
45+
...
46+
What's up? was published in 2024.
47+
48+
Fields may also be left out:
49+
50+
>>> Question.objects.raw_aggregate([{"$project": {"question_text": 1}}])
51+
52+
The ``Question`` objects returned by this query will be deferred model instances
53+
(see :meth:`~django.db.models.query.QuerySet.defer()`). This means that the
54+
fields that are omitted from the query will be loaded on demand. For example::
55+
56+
>>> for q in Question.objects.raw_aggregate([{"$project": {"question_text": 1}}]):
57+
>>> print(
58+
... q.question_text, # This will be retrieved by the original query.
59+
... q.pub_date, # This will be retrieved on demand.
60+
... )
61+
...
62+
What's new 2023-09-03 12:00:00+00:00
63+
What's up 2024-08-23 20:57:30+00:00
64+
65+
From outward appearances, this looks like the query has retrieved both the
66+
question text and published date. However, this example actually issued three
67+
queries. Only the question texts were retrieved by the ``raw_aggregate()``
68+
query -- the published dates were both retrieved on demand when they were
69+
printed.

tests/raw_query_/test_raw_aggregate.py

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -207,31 +207,20 @@ def test_missing_fields_without_PK(self):
207207
def test_annotations(self):
208208
query = [
209209
{
210-
"$lookup": {
211-
"from": "raw_query__book",
212-
"localField": "_id",
213-
"foreignField": "author_id",
214-
"as": "books",
215-
}
216-
},
217-
{"$addFields": {"book_count": {"$size": "$books"}}},
218-
{"$project": {"books": 0}},
219-
{
220-
"$group": {
221-
"_id": "$_id",
222-
"first_name": {"$first": "$first_name"},
223-
"last_name": {"$first": "$last_name"},
224-
"dob": {"$first": "$dob"},
225-
"book_count": {"$first": "$book_count"},
226-
}
210+
"$project": {
211+
"first_name": 1,
212+
"last_name": 1,
213+
"dob": 1,
214+
"birth_year": {"$year": "$dob"},
215+
},
227216
},
228217
{"$sort": {"_id": 1}},
229218
]
230219
expected_annotations = (
231-
("book_count", 3),
232-
("book_count", 0),
233-
("book_count", 1),
234-
("book_count", 0),
220+
("birth_year", 1950),
221+
("birth_year", 1920),
222+
("birth_year", 1986),
223+
("birth_year", 1932),
235224
)
236225
authors = Author.objects.order_by("pk")
237226
self.assertSuccessfulRawQuery(Author, query, authors, expected_annotations)

0 commit comments

Comments
 (0)