MongoDB C# Aggregation with LINQ
You can use LINQ syntax which gets translated into Aggregation Framework's syntax. Assuming you have following Model
class:
public class Model{ public DateTime Timestamp { get; set; } public float Value { get; set; }}
you can use where
to specify timestamp range and then use group
with null
as grouping key. MongoDB driver will translate Min
, Max
and Average
from anonymous type into $max
, $min
and $avg
from Aggregation Framework syntax
var q = from doc in Col.AsQueryable() where doc.Timestamp > DateTime.Now.AddDays(-3) where doc.Timestamp < DateTime.Now.AddDays(3) group doc by (Model)null into gr select new { Avg = (double)gr.Average(x => x.Value), Min = gr.Min(x => x.Value), Max = gr.Max(x => x.Value) };var result = q.First();
List of accumulators supported by MongoDB driver can be found here.
EDIT: the (Model)null
is required because the query has to be transformed to $group
with _id
set to null
(docs) since you want to get one result with aggregates. Casting is required just for C# compiler purpose as doc is of type Model
.
The aggregation for this is done in two steps:
$match
- Retrieve documents withTimeStamp
value between some definedminDate
andmaxDate
.$group
- Group on null. This will put all documents in a single group so we can apply an accumulator function across everything from the step 1 $match. The accumulator functions you're looking for are$min
,$max
, and$avg
.
IMongoCollection<Entity> collection = GetMyCollection();DateTime minDate = default(DateTime); // define this yourselfDateTime maxDate = default(DateTime); // define this yourselfvar match = new BsonDocument{ { "$match", new BsonDocument { { "TimeStamp", new BsonDocument { { "$and", new BsonDocument { { "$gt", minDate }, { "$lt", maxDate } } } } } }} };var group = new BsonDocument{ { "$group", new BsonDocument { { "_id", BsonNull.Value }, { "min", new BsonDocument { { "$min", "Value" } } }, { "max", new BsonDocument { { "$max", "Value" } } }, { "avg", new BsonDocument { { "$avg", "Value" } } }, }} };var result = collection.Aggregate(PipelineDefinition<Entity, BsonDocument>.Create(match, group)).Single();double min = result["min"].AsDouble;double max = result["max"].AsDouble;double avg = result["avg"].AsDouble;