Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB $first unsupported error C# driver

I've got an aggregation query in the C# driver like this:

var result = await _records.Aggregate()
                .Match(record => record.Statuses.Any(status => status.Status == currentStatus))
                .Unwind(record => record.Statuses)
                .Sort(Builders<BsonDocument>.Sort.Descending("statuses.date"))
                .Group(doc => doc["_id"], group => new { Id = group.Key, CurrentStatus = group.First()["statuses"] })
                .Match(arg => arg.CurrentStatus["status"] == BsonValue.Create(currentStatus.ToString()))
                .ToListAsync();

which matches the following shell syntax:

db.records.aggregate(
    [
        {
            $match : { "statuses.status" : "Finished" }
        },
        {
            $unwind: "$statuses"
        },
        {
            $sort: { "statuses.date":-1 }
        },
        {
            $group: {
                _id: "$_id",
                current_status: { $first: "$statuses" }
            }
        },
        {
            $match : { "current_status.status" : "Finished" }
        }
    ])

I think the C# version is not working because of the CurrentStatus = group.First()["statuses"] and the exception is:

System.NotSupportedException: get_Item of type MongoDB.Bson.BsonValue is an unsupported method in a $project or $group pipeline operator.

My approach for the First() convention is based on this:

MongoDB C# Driver First Expression Reference

Any ideas of how to translate it in a way the driver likes?

like image 645
Miguel A. Arilla Avatar asked Oct 30 '22 19:10

Miguel A. Arilla


1 Answers

After playing around with a similar example for a bit, it looks like you can do this by first calling Select on your group to get the statuses field and then call First() on that:

var result = await _records.Aggregate()
  .Match(record => record.Statuses.Any(status => status.Status == currentStatus))
  .Unwind(record => record.Statuses)
  .Sort(Builders<BsonDocument>.Sort.Descending("statuses.date"))
  .Group(doc => doc["_id"], group => new 
  { 
      Id = group.Key, 
      CurrentStatus = group.Select(x => x["statuses"]).First() 
  })
  .Match(arg => arg.CurrentStatus["status"] == BsonValue.Create(currentStatus.ToString()))
  .ToListAsync();
like image 111
JohnnyHK Avatar answered Nov 15 '22 06:11

JohnnyHK