@@ -193,7 +193,9 @@ def _build_aggregation_pipeline(self, ids, group):
193
193
projected_fields [table ][field ] = value
194
194
else :
195
195
projected_fields [key ] = value
196
- pipeline .append ({"$addFields" : projected_fields })
196
+ # Convert defaultdict to dict so it doesn't appear as
197
+ # "defaultdict(<CLASS 'dict'>, ..." in query logging.
198
+ pipeline .append ({"$addFields" : dict (projected_fields )})
197
199
if "_id" not in projected_fields :
198
200
pipeline .append ({"$unset" : "_id" })
199
201
return pipeline
@@ -428,33 +430,31 @@ def _get_aggregate_expressions(self, expr):
428
430
stack .extend (expr .get_source_expressions ())
429
431
430
432
def get_project_fields (self , columns = None , ordering = None ):
431
- fields = {}
433
+ fields = defaultdict ( dict )
432
434
for name , expr in columns or []:
435
+ collection = expr .alias if isinstance (expr , Col ) else None
433
436
try :
434
- column = expr .target .column
435
- except AttributeError :
436
- # Generate the MQL for an annotation.
437
- try :
438
- fields [name ] = expr .as_mql (self , self .connection )
439
- except EmptyResultSet :
440
- fields [name ] = Value (False ).as_mql (self , self .connection )
441
- except FullResultSet :
442
- fields [name ] = Value (True ).as_mql (self , self .connection )
443
- else :
444
- # If name != column, then this is an annotatation referencing
445
- # another column.
446
- fields [name ] = 1 if name == column else f"${ column } "
447
- if fields :
448
- # Add related fields.
449
- for alias in self .query .alias_map :
450
- if self .query .alias_refcount [alias ] and self .collection_name != alias :
451
- fields [alias ] = 1
452
- # Add order_by() fields.
453
- for alias , expression in ordering or []:
454
- nested_entity = alias .split ("." , 1 )[0 ] if "." in alias else None
455
- if alias not in fields and nested_entity not in fields :
456
- fields [alias ] = expression .as_mql (self , self .connection )
457
- return fields
437
+ fields [collection ][name ] = (
438
+ 1
439
+ # For brevity/simplicity, project {"field_name": 1}
440
+ # instead of {"field_name": "$field_name"}.
441
+ if isinstance (expr , Col ) and name == expr .target .column
442
+ else expr .as_mql (self , self .connection )
443
+ )
444
+ except EmptyResultSet :
445
+ fields [collection ][name ] = Value (False ).as_mql (self , self .connection )
446
+ except FullResultSet :
447
+ fields [collection ][name ] = Value (True ).as_mql (self , self .connection )
448
+ # Annotations (stored in None) and the main collection's fields
449
+ # should appear in the top-level of the fields dict.
450
+ fields .update (fields .pop (None , {}))
451
+ fields .update (fields .pop (self .collection_name , {}))
452
+ # Add order_by() fields.
453
+ if fields and ordering :
454
+ fields .update ({alias : expr .as_mql (self , self .connection ) for alias , expr in ordering })
455
+ # Convert defaultdict to dict so it doesn't appear as
456
+ # "defaultdict(<CLASS 'dict'>, ..." in query logging.
457
+ return dict (fields )
458
458
459
459
def _get_ordering (self ):
460
460
"""
0 commit comments