-
Type: Bug
-
Resolution: Works as Designed
-
Priority: Major - P3
-
None
-
Affects Version/s: 2.11.5
-
Component/s: Linq
-
None
-
Environment:Windows 10, .NET 5
Suppose I have a collection, mapped in C# as a "DrivenRoute", held in MongoDB as:
[ { "_t": ["DrivenRoute"], "Stops": [{ "StationId": "A" }, { "StationId": "B" }, { "StationId": "C" }, { "StationId": "D" }] }, { "_t": ["DrivenRoute"], "Stops": [{ "StationId": "A" }, { "StationId": "B" }, { "StationId": "C" }, { "StationId": "D" }] }, { "_t": ["DrivenRoute"], "Stops": [{ "StationId": "A" }, { "StationId": "B" }, { "StationId": "C" }, { "StationId": "D" }] }, { "_t": ["DrivenRoute"], "Stops": [{ "StationId": "B" }, { "StationId": "C" }, { "StationId": "D" }, { "StationId": "E" }] } ]
Each entry in "Stops" is mapped in C# as a "DrivenRouteStop".
I want to count how many times each StationId has appeared in any DrivenRoute. In MQL I can use:
[{ $unwind: { path: '$Stops' } }, { $group: { _id: '$Stops.StationId', Stops: { $sum: 1 } } }]
This produces the correct result:
[{ "_id": "B", "Stops": 4 },{ "_id": "A", "Stops": 3 },{ "_id": "C", "Stops": 4 },{ "_id": "E", "Stops": 1 },{ "_id": "D", "Stops": 4 }]
Now I try to write the same query in C# using the aggregation pipeline syntax against strongly typed objects:
var result = await _activitiesCollection.OfType<DrivenRoute>().Aggregate() .Unwind<DrivenRoute, DrivenRouteStop>(dr => dr.Stops) .Group(stop => stop.StationId, g => new { StationId = g.Key, TotalStops = g.Count() }).ToListAsync();
Whilst this pipeline runs, I receive an incorrect result:
[{ "_id": null, "Stops": 16 }]
It appears that the C# driver is generating the wrong path on the "unwind" stage. Instead of using "$Stops.StationId", it simply uses "StationId". The unwind operation correctly preserves the "Stops" field as an object, but C# tries to access StationId directly as if ReplaceRoot had been used.
[{$unwind: { path: '$Stops' }}, {$group: { _id: '$StationId', Stops: { $sum: 1 } }}]
Whilst I could revert to writing this query using BsonDocument instead of strongly typed objects, this defeats the purpose of being able to use strongly typed pipelines, and could result in incorrect results due to field name changes or similar, which wouldn't be picked up by the compiler at compile-time, or by Intellisense at design-time.
- mentioned in
-
Page Loading...