Reputation: 667
I'm having problem the following LINQ expression on Mongo using the 2.1 C# driver running Mongo 3.0. Selecting the Id works fine but not selecting the A.
The following simple test demonstrates the error I'm getting.
Specified method is not supported. at MongoDB.Driver.Linq.Processors.AccumulatorBinder.GetAccumulatorArgument(Expression node)
If it is not supported, any suggestions how to work around it without having to unwind the queryable first? I know that I could use the mongo aggregate framework but that is not desired since we are not exposed to that here and I do not want mongo specific syntax at this level.
[Test]
public void TestLinqSelectOnGroupBy()
{
MongoClient mongoClient = new MongoClient();
var repo = mongoClient.GetDatabase("GroupSelect");
var a = new A() { Id = "1", Group = "A" };
var col = repo.GetCollection<A>("A");
col.InsertOneAsync(a);
var allA = col.AsQueryable(); // adding .ToArray(); will obviously make it work but that is not very efficient
var works = allA.GroupBy(x => x.Group).Select(x => x.First().Id).ToArray();
var fails = allA.GroupBy(x => x.Group).Select(x => x.First()).ToArray();
}
private class A
{
public string Id { get; set; }
public string Group { get; set; }
}
Upvotes: 3
Views: 5393
Reputation: 4278
I stumbled across an answer from another Stack Overflow question. The issue is the First()
call itself.
Quoting octavioccl from that answer:
var statusesCollection = database.GetCollection<Status>("statuses"); var result= statusesCollection.AsQueryable() .OrderByDescending(e=>e.date) .GroupBy(e=>e.payment) .Select(g=>new Status{_id =g.First()._id, payment = g.Key, code=g.First().code, date=g.First().date } ) .ToList();
Now you may wondering why I had to project the result to a new instance of
Status
class if I could get the same result callingFirst
extension method from each group? Unfortunately that is not supported yet. One of the reason is because the Linq provider is using [$first][1] operation when it build the aggregation pipeline, and that is how$first
operation works.
So for your case, you should just be able to do:
allA.GroupBy(x => x.Group).Select(x => new A
{
Id = x.First().Id,
Group = x.First().Group
}).ToArray();
I only found your question while still seeing if this particular thing was still an issue and it still seems to be which is a little unfortunate.
Upvotes: 5