MongoDB C# Aggregation with LINQ

若如初见. 提交于 2019-12-22 08:11:40

问题


I have a mongo object with these fields:

DateTime TimeStamp;
float    Value;

How can I get the aggregation pipeline, in C#, with LINQ, to get the minimum, maximum and average of Value over a specific timestamp range?

I have seen a few aggregation examples, but I don't quite get it. Having an example on a simple case like this would certainly (hopefully) make me understand it.


回答1:


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.




回答2:


The aggregation for this is done in two steps:

  1. $match - Retrieve documents with TimeStamp value between some defined minDate and maxDate.
  2. $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 yourself
DateTime maxDate = default(DateTime); // define this yourself

var 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;


来源:https://stackoverflow.com/questions/52065458/mongodb-c-sharp-aggregation-with-linq

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!