【发布时间】:2019-02-03 12:50:44
【问题描述】:
我有一个带有这些字段的 mongo 对象:
DateTime TimeStamp;
float Value;
如何在 C# 中使用 LINQ 获取聚合管道,以获取特定时间戳范围内 Value 的最小值、最大值和平均值?
我看过一些聚合示例,但我不太明白。有一个像这样的简单案例的例子肯定会(希望)让我理解它。
【问题讨论】:
标签: c# mongodb aggregation
我有一个带有这些字段的 mongo 对象:
DateTime TimeStamp;
float Value;
如何在 C# 中使用 LINQ 获取聚合管道,以获取特定时间戳范围内 Value 的最小值、最大值和平均值?
我看过一些聚合示例,但我不太明白。有一个像这样的简单案例的例子肯定会(希望)让我理解它。
【问题讨论】:
标签: c# mongodb aggregation
您可以使用翻译成聚合框架语法的 LINQ 语法。假设您有以下 Model 类:
public class Model
{
public DateTime Timestamp { get; set; }
public float Value { get; set; }
}
您可以使用where 指定时间戳范围,然后使用group 和null 作为分组键。 MongoDB 驱动程序会将 Min、Max 和 Average 从匿名类型转换为来自聚合框架语法的 $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# 编译器的目的需要强制转换。
【讨论】:
对此的聚合分两步完成:
$match - 检索 TimeStamp 值介于某些定义的 minDate 和 maxDate 之间的文档。$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;
【讨论】: