@@ -26,26 +26,39 @@ def __init__(self, *args, **kwargs):
26
26
super ().__init__ (* args , ** kwargs )
27
27
self ._group_pipeline = None
28
28
29
- def _get_group_alias_column (self , col , annotation_group_idx ):
30
- """Generate alias and replacement for group columns."""
29
+ def _get_group_alias_column (self , expr , annotation_group_idx ):
30
+ """
31
+ Generate a dummy field for use in ids fields in $group.
32
+
33
+ If the column is a composite expression (not a single column),
34
+ it creates an auxiliary field and pass it through the flow.
35
+ When a foreign field is needed in the ids, escape the dot (.) using GROUP_SEPARATOR.
36
+ """
31
37
replacement = None
32
- if not isinstance (col , Col ):
38
+ if isinstance (expr , Col ):
39
+ col = expr
40
+ else :
33
41
alias = f"__annotation_group{ next (annotation_group_idx )} "
34
- col_expr = self ._get_column_from_expression (col , alias )
42
+ col_expr = self ._get_column_from_expression (expr , alias )
35
43
replacement = col_expr
36
44
col = col_expr
37
45
if self .collection_name == col .alias :
38
46
return col .target .column , replacement
39
47
return f"{ col .alias } { self .GROUP_SEPARATOR } { col .target .column } " , replacement
40
48
41
49
def _get_column_from_expression (self , expr , alias ):
42
- """Get column target from expression."""
50
+ """
51
+ Create a new column with the specified output type and alias to hold the aggregate value.
52
+
53
+ This function generates a column target from the given expression, setting the column's
54
+ output type and assigning the provided alias to the column.
55
+ """
43
56
column_target = expr .output_field .__class__ ()
44
57
column_target .db_column = alias
45
58
column_target .set_attributes_from_name (alias )
46
59
return Col (self .collection_name , column_target )
47
60
48
- def _prepare_expressions_for_pipeline (self , expression , target , count ):
61
+ def _prepare_expressions_for_pipeline (self , expression , target , annotation_group_idx ):
49
62
"""
50
63
Prepare expressions for the aggregation pipeline.
51
64
@@ -64,7 +77,9 @@ def _prepare_expressions_for_pipeline(self, expression, target, count):
64
77
replacements = {}
65
78
group = {}
66
79
for sub_expr in self ._get_aggregate_expressions (expression ):
67
- alias = f"__aggregation{ next (count )} " if sub_expr != expression else target
80
+ alias = (
81
+ f"__aggregation{ next (annotation_group_idx )} " if sub_expr != expression else target
82
+ )
68
83
column_target = sub_expr .output_field .__class__ ()
69
84
column_target .db_column = alias
70
85
column_target .set_attributes_from_name (alias )
0 commit comments