3

I am using Mongo C# v 2.11.5 to group users by their CategoryId. I would like the variable list_of_groups to contain a list of groups, where each group has a list of all the documents in the group, where each document contains all its individual properties. I don't want to apply any accumulator functions on any fields.

The UserGroup class is:

public class UserGroup { public string gid {get; set;} public List<Users> users { get; set; } } 

My grouping query is

 var list_of_groups = UserCollection .Aggregate() .Group(usr => usr.CategoryId, g => new UserGroup { gid = g.Key, users = g.ToList() }) .ToList<UserGroup>(); 

I would like to create a "list of lists", where each inner list contains all the documents of its grouping i.e. this type of structure:

List<List<UserGroup>>( - List1<UserGroup> (list of complete documents belonging to CategoryId 1) - List2<UserGroup> (list of complete documents belonging to CategoryId 2) - List3<UserGroup> (list of complete documents belonging to CategoryId 3) ) 

The doesn't work as the following error is generated at runtime:

System.NotSupportedException HResult=0x80131515 Message=Specified method is not supported. Source=MongoDB.Driver 

Can anyone point out what I'm missing here? I've been going in circles for a while now. Should I not being using the Group function, and maybe some other function is more appropriate since I don't want to apply any accumulator functions, and because I want each document in each group to have all its properties available?

Stack Trace:

 at MongoDB.Driver.Linq.Processors.AccumulatorBinder.GetAccumulatorArgument(Expression node) at MongoDB.Driver.Linq.Processors.AccumulatorBinder.TryGetAccumulatorTypeAndArgument(PipelineExpression node, AccumulatorType& accumulatorType, Expression& argument) at MongoDB.Driver.Linq.Processors.AccumulatorBinder.VisitPipeline(PipelineExpression node) at MongoDB.Driver.Linq.Expressions.PipelineExpression.Accept(ExtensionExpressionVisitor visitor) at MongoDB.Driver.Linq.Expressions.ExtensionExpression.Accept(ExpressionVisitor visitor) at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) at MongoDB.Driver.Linq.Processors.AccumulatorBinder.Bind(Expression node, IBindingContext bindingContext) at MongoDB.Driver.Linq.Processors.EmbeddedPipeline.EmbeddedPipelineBinder.Bind(Expression node, IBindingContext parent) at MongoDB.Driver.Linq.Processors.SerializationBinder.BindEmbeddedPipeline(MethodCallExpression node) at MongoDB.Driver.Linq.Processors.SerializationBinder.VisitMethodCall(MethodCallExpression node) at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor) at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) at MongoDB.Driver.Linq.Processors.SerializationBinder.Visit(Expression node) at System.Linq.Expressions.ExpressionVisitor.VisitMemberAssignment(MemberAssignment node) at System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding node) at System.Linq.Expressions.ExpressionVisitor.Visit[T](ReadOnlyCollection`1 nodes, Func`2 elementVisitor) at System.Linq.Expressions.ExpressionVisitor.VisitMemberInit(MemberInitExpression node) at System.Linq.Expressions.MemberInitExpression.Accept(ExpressionVisitor visitor) at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) at MongoDB.Driver.Linq.Processors.SerializationBinder.Visit(Expression node) at MongoDB.Driver.Linq.Processors.SerializationBinder.Bind(Expression node, IBindingContext context, Boolean isClientSideProjection) at MongoDB.Driver.Linq.Processors.PipelineBindingContext.Bind(Expression node, Boolean isClientSideProjection) at MongoDB.Driver.Linq.Processors.PipelineBindingContext.Bind(Expression node) at MongoDB.Driver.Linq.Translators.AggregateGroupTranslator.BindGroup[TKey,TDocument,TResult](PipelineBindingContext bindingContext, Expression`1 groupProjector, IBsonSerializer`1 parameterSerializer, Expression keySelector) at MongoDB.Driver.Linq.Translators.AggregateGroupTranslator.Translate[TKey,TDocument,TResult](Expression`1 idProjector, Expression`1 groupProjector, IBsonSerializer`1 parameterSerializer, IBsonSerializerRegistry serializerRegistry, ExpressionTranslationOptions translationOptions) at MongoDB.Driver.GroupExpressionProjection`3.Render(IBsonSerializer`1 documentSerializer, IBsonSerializerRegistry serializerRegistry) at MongoDB.Driver.PipelineStageDefinitionBuilder.<>c__DisplayClass19_0`2.<Group>b__0(IBsonSerializer`1 s, IBsonSerializerRegistry sr) at MongoDB.Driver.DelegatedPipelineStageDefinition`2.Render(IBsonSerializer`1 inputSerializer, IBsonSerializerRegistry serializerRegistry) at MongoDB.Driver.AppendedStagePipelineDefinition`3.Render(IBsonSerializer`1 inputSerializer, IBsonSerializerRegistry serializerRegistry) at MongoDB.Driver.MongoCollectionImpl`1.Aggregate[TResult](IClientSessionHandle session, PipelineDefinition`2 pipeline, AggregateOptions options, CancellationToken cancellationToken) at MongoDB.Driver.MongoCollectionImpl`1.<>c__DisplayClass19_0`1.<Aggregate>b__0(IClientSessionHandle session) at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSession[TResult](Func`2 func, CancellationToken cancellationToken) at MongoDB.Driver.MongoCollectionImpl`1.Aggregate[TResult](PipelineDefinition`2 pipeline, AggregateOptions options, CancellationToken cancellationToken) at MongoDB.Driver.CollectionAggregateFluent`2.ToCursor(CancellationToken cancellationToken) 
4
  • 1
    What do you expect from the .Aggregate()? Here is the doc on this method. learn.microsoft.com/en-us/dotnet/api/…. Commented Jan 6, 2021 at 13:51
  • Does this answer your question? Using Linq to group a list of objects into a new grouped list of list of objects Commented Jan 6, 2021 at 13:51
  • @DragandDrop Not sure we're considering the same Aggregate() method- I'm using the IMongoCollectionExtensions.Aggregate which returns an IAggregateFluent<TDocument> from mongodb.github.io/mongo-csharp-driver/2.8/apidocs/html/… Commented Jan 6, 2021 at 14:52
  • Ma bad. Never used that one. I missed the tag aggregation-framework, that was a good hint of it beeing a framework specific method. For my defence I often see code with naked Aggregate not related to that framework, as it's the first method in the Crtl space suggestion. It's sometimes use as a place holder or go-get-it method. Commented Jan 7, 2021 at 8:36

1 Answer 1

4

The problem you're facing here is that everything that's within .Group() method should get translated into corresponding MongoDB / Aggregation Framework operator and obviously there's no .ToList() counterpart. Therefore, there's no path forward with LINQ if you want to return a list of documents and you have to use Aggregation Framework's syntax directly and take advantage of $$ROOT variable:

public class UserGroup { [BsonElement("_id")] public string gid { get; set; } public List<User> users { get; set; } } var groupDef = new BsonDocument() { { "_id", "$CategoryId" }, { "users", new BsonDocument(){ { "$push", "$$ROOT" } } } }; var res = collection.Aggregate().Group<UserGroup>(groupDef).ToList(); 
Sign up to request clarification or add additional context in comments.

2 Comments

How can this example be adapted, if only the groups containing more than n users (for example 2) should be returned? Is it possible to write the query without using the BsonDocument (linq or fluentaggregate style) using the new linq3 provider from the mongodb c# driver 2.14?
@RickyTad please open another question and describe your case

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.