MongoDB 使用 LINQ 的 C# 聚合

MongoDB C# Aggregation with LINQ

我有一个包含这些字段的 mongo 对象:

DateTime TimeStamp;
float    Value;

如何在 C# 中使用 LINQ 获取聚合管道,以获取特定时间戳范围内的最小值、最大值和平均值?

我看过一些聚合示例,但我不太明白。有一个像这样的简单案例的例子肯定(希望)让我理解它。

此聚合分两步完成:

  1. $match - 检索 TimeStamp 值介于某些定义的 minDatemaxDate.
  2. 之间的文档
  3. $group - 分组为空。这会将所有文档放在一个组中,因此我们可以对步骤 1 $match 中的所有内容应用累加器函数。您要查找的累加器函数是 $min$max$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;

您可以使用转换为聚合框架语法的 LINQ 语法。假设您有以下 Model class:

public class Model
{
    public DateTime Timestamp { get; set; }
    public float Value { get; set; }
}

您可以使用 where 指定时间戳范围,然后使用 groupnull 作为分组键。 MongoDB 驱动程序会将匿名类型的 MinMaxAverage 转换为聚合框架语法中的 $max$min$avg

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();

可以找到 MongoDB 驱动程序支持的累加器列表 here

编辑:(Model)null 是必需的,因为必须将查询转换为 $group,并将 _id 设置为 null (docs),因为您想要通过聚合获得一个结果。由于 doc 的类型为 Model.

,因此 C# 编译器需要强制转换