While using C# MongoDB Driver on simple queries we quite often use a following pattern:
var query = Collection.AsQueryable();
query = BuildQuery(query, request)
// Same queryable used to get total and actual values for pagination
total = query.Count();
values = query.Skip(request.Ski[).Take(request.Take);
return { Values = values, Total = total };
Overall everything worked ok till we got a use cases with 100K+ entries matching documents and it started to take 30+ seconds.
It turns out that C# driver converts this request into following aggregation:
db.getCollection('xyzEntity').aggregate([ {
"$group" : {
"_id" : 1,
"__result" : {
"$sum" : 1
}
}
}])
which performs much slower than getCollection().find({}).count()
which is using index.
According to documentation (*) this is by design but this is very confusing to me. Why it is implemented via aggregation? Probably idea is that I can pass query within Count but how I can change this query to use indexes?
It turns out that this we can help aggregation by sorting things by index: https://stackoverflow.com/a/56427875/11768
As for linq solution is to change count line in following way:
var total = query.OrderBy(d => d.Id).Count()