Search code examples
c#mongodbmongodb-.net-driver

Aggregate field must be defined as an expression inside an object error


Trying to port below mongodb aggregation query to c# but getting the error -

Command aggregate failed: the group aggregate field 'ProductType' must be defined as an expression inside an object.

Any thoughts on what is wrong with the c# code?

db.collectionName.aggregate([
        { $match: activeTrial},
        {  $project: {_id:1, CustomerType: 1, ProductType: 1} },
        { $group: {_id: {"cust": "$CustomerType", "prod" : "$ProductType"}, count: {$sum: 1}}},
          ]).toArray()

collectionName.Aggregate()
                .Match(filter)
                .Project(x => new {x.CustomerType, x.SubscriptionId, x.ProductType})
                .Group(x => new { x.ProductType, x.CustomerType }, g => new ActiveTrialsByProduct()
                {
                    ProductType = g.Key.ProductType,
                    CustomerType = g.Key.CustomerType,
                    ActiveTrials = g.Count()
                }).ToList();

Here is the collection..

{  
    "CustomerType" : "CustA",   
    "ProductType" : "ProdA", 
}
{  
    "CustomerType" : "CustA",   
    "ProductType" : "ProdB", 
}
{  
    "CustomerType" : "CustA",   
    "ProductType" : "ProdB", 
}
{  
    "CustomerType" : "CustA",   
    "ProductType" : "ProdA", 
}

Solution

  • The group method doesn't know about g.Key.ProductType so we have to project the elements of the key in the project method.

    collectionName.Aggregate()
                    .Match(filter)
                    .Project(x => new {x.CustomerType, x.ProductName, x.SubscriptionId })
                    .Group(x => new { x.ProductName, x.CustomerType }, g => new 
                    {
                        Id = g.Key,
                        ActiveTrials = g.Count()
                    })
                    .Project(x => new ActiveTrialsByProduct()
                    {
                        CustomerType = x.Id.CustomerType,
                        Product = x.Id.ProductName,
                        ActiveTrials = x.ActiveTrials
                    }).ToList();