Skip to content

Commit d7d40c3

Browse files
timgrahamWaVEV
authored andcommitted
add support for annotations, group by, and ordering
1 parent fd57ce8 commit d7d40c3

File tree

2 files changed

+51
-2
lines changed

2 files changed

+51
-2
lines changed

django_mongodb_backend/compiler.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def _get_column_from_expression(self, expr, alias):
5353
Create a column named `alias` from the given expression to hold the
5454
aggregate value.
5555
"""
56-
column_target = expr.output_field.__class__()
56+
column_target = expr.output_field.clone()
5757
column_target.db_column = alias
5858
column_target.set_attributes_from_name(alias)
5959
return Col(self.collection_name, column_target)
@@ -81,7 +81,7 @@ def _prepare_expressions_for_pipeline(self, expression, target, annotation_group
8181
alias = (
8282
f"__aggregation{next(annotation_group_idx)}" if sub_expr != expression else target
8383
)
84-
column_target = sub_expr.output_field.__class__()
84+
column_target = sub_expr.output_field.clone()
8585
column_target.db_column = alias
8686
column_target.set_attributes_from_name(alias)
8787
inner_column = Col(self.collection_name, column_target)

tests/model_fields_/test_embedded_model.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
1+
import operator
2+
13
from django.core.exceptions import ValidationError
24
from django.db import models
5+
from django.db.models import (
6+
ExpressionWrapper,
7+
F,
8+
IntegerField,
9+
Max,
10+
Sum,
11+
)
312
from django.test import SimpleTestCase, TestCase
413
from django.test.utils import isolate_apps
514

@@ -104,6 +113,46 @@ def test_nested(self):
104113
)
105114
self.assertCountEqual(Book.objects.filter(author__address__city="NYC"), [obj])
106115

116+
def truncate_ms(self, value):
117+
"""Truncate microsends to millisecond precision as supported by MongoDB."""
118+
return value.replace(microsecond=(value.microsecond // 1000) * 1000)
119+
120+
def test_ordering_by_embedded_field(self):
121+
query = Holder.objects.filter(data__integer__gt=3).order_by("-data__integer").values("pk")
122+
expected = [{"pk": e.pk} for e in list(reversed(self.objs[4:]))]
123+
self.assertSequenceEqual(query, expected)
124+
125+
def test_ordering_grouping_by_embedded_field(self):
126+
expected = sorted(
127+
(Holder.objects.create(data=Data(integer=x)) for x in range(6)),
128+
key=lambda x: x.data.integer,
129+
)
130+
query = (
131+
Holder.objects.annotate(
132+
group=ExpressionWrapper(F("data__integer") + 5, output_field=IntegerField())
133+
)
134+
.values("group")
135+
.annotate(max_auto_now=Max("data__auto_now"))
136+
.order_by("data__integer")
137+
)
138+
query_response = [{**e, "max_auto_now": self.truncate_ms(e["max_auto_now"])} for e in query]
139+
self.assertSequenceEqual(
140+
query_response,
141+
[
142+
{"group": e.data.integer + 5, "max_auto_now": self.truncate_ms(e.data.auto_now)}
143+
for e in expected
144+
],
145+
)
146+
147+
def test_ordering_grouping_by_sum(self):
148+
[Holder.objects.create(data=Data(integer=x)) for x in range(6)]
149+
qs = (
150+
Holder.objects.values("data__integer")
151+
.annotate(sum=Sum("data__integer"))
152+
.order_by("sum")
153+
)
154+
self.assertQuerySetEqual(qs, [0, 2, 4, 6, 8, 10], operator.itemgetter("sum"))
155+
107156

108157
@isolate_apps("model_fields_")
109158
class CheckTests(SimpleTestCase):

0 commit comments

Comments
 (0)