Unwind then Group aggregation in MongoDB C#

Juzzbott picture Juzzbott · May 26, 2015 · Viewed 12.7k times · Source

I'm having some trouble with the new C# 2.0 MongoDB driver and the aggregation pipeline.

Basically, I'm trying to return the most popular elements within an array field on the object. The field type is: IList<string> FavouritePlaceIds { get; set; }.

I have the following MongoDB aggregation which is working as expected:

db.users.aggregate([
    { $unwind : "$FavouritePlaceIds" },
    { $group: { "_id": "$FavouritePlaceIds", "count": {$sum: 1}}}, 
    { $sort : { "count": -1 }}
])

However, the issue is now trying to translate that into C# code using the new MongoDB driver 2.0. I've been using the following link for help with the aggregation pipeline: http://mongodb.github.io/mongo-csharp-driver/2.0/reference/driver/crud/reading/#unwind

I've got the following so far for my aggregation pipeline:

var pipeline = usersCollection.Aggregate()
                .Unwind(i => i.FavouritePlaceIds)
                .Group(i => i.FavouritePlaceIds, g => new { FavouritePlaceIds = g.Key, Count = g.Count() })
                .SortByDescending(i => i.Count);

When I go to compile that code, I get following message:

'BsonDocument' does not contain a definition for 'FavouritePlaceIds' and no extension method 'FavouritePlaceIds' accepting a first argument of type 'BsonDocument' could be found...

The error is occuring on the first parameter (i => i.FavouritePlaceIds) of the Group() method.

Reading the notes at the link provided under the group section, it mentions that:

Because $unwind is a type of projection, you must provide a return type.

So, I'm assuming that I'm not specifying a correct return type, which is why it's expecting a BsonDocument object, and failing to compile.

So, how can I specify the correct return type to use in the Group method?

Answer

i3arnon picture i3arnon · May 26, 2015

When you let Unwind infer the type parameters it will use the collection type for TResult and BsonDocument for TNewResult.

If you want to use a specific type and not BsonDocument you need to add these type parameters:

var pipeline = usersCollection.Aggregate()
    .Unwind<OriginalType, NewResultType>(....

As always, you need to make sure the operation actually returns something that can be of that type.