[CSHARP-4555] Linq3 projection stage generated by group does not use registered class maps Created: 02/Mar/23  Updated: 01/Nov/23

Status: Backlog
Project: C# Driver
Component/s: LINQ3
Affects Version/s: 2.19.0
Fix Version/s: None

Type: Bug Priority: Unknown
Reporter: nesc58 N/A Assignee: Unassigned
Resolution: Unresolved Votes: 0
Labels: triage
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
related to CSHARP-4819 ReplaceWith not respecting custom ele... Investigating

 Description   

Summary

Generated projection stage does not use registered class maps.

How to Reproduce

BsonClassMap.RegisterClassMap(new ItemClassMap());
BsonClassMap.RegisterClassMap(new SubItemClassMap());
BsonClassMap.RegisterClassMap(new AggregationClassMap());var pipeline = PipelineDefinitionBuilder.For<Item>()
    .Group(
        e => e.Date,
        grouping => new Aggregation
        {
            Date = grouping.Key, Count = grouping.Sum(item => item.Items.Length)
        });var renderedPipeline = pipeline.Render(BsonSerializer.LookupSerializer<Item>(), BsonSerializer.SerializerRegistry, LinqProvider.V3).Documents;foreach (var doc in renderedPipeline) Console.WriteLine(doc.ToString());
 
public class SubItem
{
    public string Name { get; set; }
}
 
public class Item
{
    public string Id { get; set; }
    public DateTime Date { get; set; }
    public SubItem[] Items { get; set; }
}
 
public class Aggregation
{
    public DateTime Date { get; set; }
    public long Count { get; set; }
}
 
public class SubItemClassMap : BsonClassMap<SubItem>
{
    public SubItemClassMap()
    {
        MapMember(e => e.Name).SetElementName("name");
    }
}
 
public class ItemClassMap : BsonClassMap<Item>
{
    public ItemClassMap()
    {
        MapIdField(e => e.Id).SetIdGenerator(StringObjectIdGenerator.Instance);
        MapMember(e => e.Date).SetElementName("date");
        MapMember(e => e.Items).SetElementName("items");
    }
}
 
public class AggregationClassMap : BsonClassMap<Aggregation>
{
    public AggregationClassMap()
    {
        MapMember(e => e.Date).SetElementName("date");
        MapMember(e => e.Count).SetElementName("count");
    }
} 

The generated documents looks following:

[
  { "$group" : { 
      "_id" : "$date", 
      "__agg0" : { "$sum" : { "$size" : "$items" } } 
  }}
  { "$project" : {
      "Date" : "$_id", 
      "Count" : { "$toLong" : "$__agg0" }, 
      "_id" : 0
  }}
]

I've expected the following

[
  { "$group" : { 
      "_id" : "$date", 
      "__agg0" : { "$sum" : { "$size" : "$items" } } 
  }}
  { "$project" : {
      "date" : "$_id", 
      "count" : { "$toLong" : "$__agg0" },
      "_id" : 0
  }}
] 

The 2.18.0 driver generates a $convert step instead of the $toLong. Using $toLong seems to be correct for 2.19.0



 Comments   
Comment by nesc58 N/A [ 23/Jun/23 ]

Hi robert@mongodb.com 

is there something new on this topic? Are there any reasons for creating a new class map internally? Is this an error by my own?

Comment by nesc58 N/A [ 25/May/23 ]

I have found something really special in the MemberInitExpressionToAggregationExpressionTranslator which is used to translate the projection stage expression.

At the beginning of the method 
public static AggregationExpression Translate(TranslationContext context, MemberInitExpression expression)
a new classmap will be created instead of search for an already existing class map.
I have no idea how the code looks at 2.18.x but something have changed for using existing class maps

Comment by nesc58 N/A [ 28/Mar/23 ]

Error still exists in 2.19.1

Comment by Robert Stam [ 07/Mar/23 ]

Thanks for reporting this. I will investigate further before long.

Generated at Wed Feb 07 21:48:35 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.