Skip to content

Commit 3e2c32d

Browse files
committed
Wrap query for global aggregation
1 parent 23f4792 commit 3e2c32d

File tree

2 files changed

+20
-5
lines changed

2 files changed

+20
-5
lines changed

django_mongodb_backend/compiler.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ def __init__(self, *args, **kwargs):
3838
self.subqueries = []
3939
# Atlas search stage.
4040
self.search_pipeline = []
41+
self.wrap_for_global_aggregation = False
4142

4243
def _get_group_alias_column(self, expr, annotation_group_idx):
4344
"""Generate a dummy field for use in the ids fields in $group."""
@@ -234,11 +235,8 @@ def _build_aggregation_pipeline(self, ids, group):
234235
"""Build the aggregation pipeline for grouping."""
235236
pipeline = []
236237
if not ids:
237-
group["_id"] = None
238-
pipeline.append({"$group": group})
239-
# It may be a bug, $$NOW has to be called to be reachable in the rest of the pipeline.
240-
pipeline.append({"$set": {"__now": "$$NOW"}})
241-
pipeline.append({"$unionWith": {"pipeline": [{"$documents": [{}]}]}})
238+
pipeline.append({"$group": {"_id": None, **group}})
239+
self.wrap_for_global_aggregation = True
242240
else:
243241
group["_id"] = ids
244242
pipeline.append({"$group": group})

django_mongodb_backend/query.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ def __init__(self, compiler):
5656
# $lookup stage that encapsulates the pipeline for performing a nested
5757
# subquery.
5858
self.subquery_lookup = None
59+
self.wrap_for_global_aggregation = compiler.wrap_for_global_aggregation
5960

6061
def __repr__(self):
6162
return f"<MongoQuery: {self.match_mql!r} ORDER {self.ordering!r}>"
@@ -91,6 +92,22 @@ def get_pipeline(self):
9192
pipeline.append({"$match": self.match_mql})
9293
if self.aggregation_pipeline:
9394
pipeline.extend(self.aggregation_pipeline)
95+
if self.wrap_for_global_aggregation:
96+
pipeline = [
97+
{"$collStats": {}},
98+
{
99+
"$lookup": {
100+
"from": self.compiler.collection_name,
101+
"as": "wrapped",
102+
"pipeline": pipeline,
103+
}
104+
},
105+
{
106+
"$replaceWith": {
107+
"$cond": [{"$eq": ["$wrapped", []]}, {}, {"$first": "$wrapped"}]
108+
}
109+
},
110+
]
94111
if self.project_fields:
95112
pipeline.append({"$project": self.project_fields})
96113
if self.combinator_pipeline:

0 commit comments

Comments
 (0)