Skip to content

Commit c082f0d

Browse files
committed
Remove $facet in top level group stages
1 parent 20b24e3 commit c082f0d

File tree

3 files changed

+21
-15
lines changed

3 files changed

+21
-15
lines changed

django_mongodb_backend/aggregates.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ def count(self, compiler, connection, resolve_inner_expression=False):
5252
# If distinct=True or resolve_inner_expression=False, sum the size of the
5353
# set.
5454
lhs_mql = process_lhs(self, compiler, connection, as_expr=True)
55+
lhs_mql = {"$ifNull": [lhs_mql, []]}
5556
# None shouldn't be counted, so subtract 1 if it's present.
5657
exits_null = {"$cond": {"if": {"$in": [{"$literal": None}, lhs_mql]}, "then": -1, "else": 0}}
5758
return {"$add": [{"$size": lhs_mql}, exits_null]}

django_mongodb_backend/compiler.py

Lines changed: 3 additions & 15 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,21 +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({"$facet": {"group": [{"$group": group}]}})
239-
pipeline.append(
240-
{
241-
"$addFields": {
242-
key: {
243-
"$getField": {
244-
"input": {"$arrayElemAt": ["$group", 0]},
245-
"field": key,
246-
}
247-
}
248-
for key in group
249-
}
250-
}
251-
)
238+
pipeline.append({"$group": {"_id": None, **group}})
239+
self.wrap_for_global_aggregation = True
252240
else:
253241
group["_id"] = ids
254242
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)