-
Type: Bug
-
Resolution: Fixed
-
Priority: Major - P3
-
Affects Version/s: 2.11.3
-
None
I am encountering a problem where custom serializers I have previously registered are not being used to convert types I use in an aggregation pipeline.
Assume I have these types:
public enum TestEnum { Foo, Bar, Baz } public record TestEntity(string Id, string Category, TestEnum EnumValue);
where TestEnum will be my custom type. I am registering the type as follows:
BsonClassMap.RegisterClassMap<TestEntity>(cm => { cm.MapIdProperty(e => e.Id); cm.MapProperty(e => e.Category) .SetElementName("category"); cm.MapProperty(e => e.EnumValue) .SetElementName("enum_value") .SetSerializer(new TestEnumSerializer()); });
TestEnumSerializer is a SerializerBase<TestEnum> that represents the enum values as the strings "my_foo", "my_bar" and "my_baz".
I am inserting some entities as follows:
IMongoCollection<TestEntity> collection = db.GetCollection<TestEntity>("test_collection"); collection.InsertOne(new TestEntity("1", "cat1", TestEnum.Foo)); collection.InsertOne(new TestEntity("2", "cat1", TestEnum.Bar)); collection.InsertOne(new TestEntity("3", "cat2", TestEnum.Bar));
and I can confirm that the entities get persisted as I expected:
/* 1 */ { "_id" : "1", "category" : "cat1", "enum_value" : "my_foo" }/* 2 */ { "_id" : "2", "category" : "cat1", "enum_value" : "my_bar" }/* 3 */ { "_id" : "3", "category" : "cat2", "enum_value" : "my_bar" }
If I now perform the following aggregation:
var bars = collection.Aggregate() .Group( e => e.Category, group => new { NumBars = group.Count(e2 => e2.EnumValue == TestEnum.Bar) }) .ToList();
I can see that the produced query looks as follows:
"pipeline": [ { "$group": { "_id": "$category", "NumBars": { "$sum": { "$cond": [ { "$eq": [ "$enum_value", 1 ] }, 1, 0 ] } } } } ]
Note that it compares the $enum_value to 1 instead of "my_bar", which makes the match fail and return a wrong result.
The 1 is the enum's ordinal value, which probably gets used because of the implicit conversion added in https://jira.mongodb.org/browse/CSHARP-131
Since it appears to be using BsonType mappers instead of registered serializers, it is possible to add custom type mappers for types that do not have an implicit conversion using BsonTypeMapper.RegisterCustomTypeMapper. However, since the enum gets implicitly converted to an ordinal value before any custom type mappers are checked, I was unable to find a workaround.
I have added the full source code of the test class I used as an attachment.
- is related to
-
CSHARP-4066 Only use regex filters against string properties that are serialized as strings
- Closed