Агрегация MongoDB C# с LINQ
У меня есть объект mongo с этими полями:
DateTime TimeStamp;
float Value;
Как я могу получить конвейер агрегации в C# с помощью LINQ, чтобы получить минимальное, максимальное и среднее значение в определенном диапазоне временных меток?
Я видел несколько примеров агрегации, но я не совсем понимаю это. Имея пример в таком простом случае, как этот, безусловно (надеюсь) заставит меня понять его.
2 ответов:
Вы можете использовать синтаксис LINQ, который переводится в синтаксис Aggregation Framework. Предположим, что у вас есть следующий класс
Model:public class Model { public DateTime Timestamp { get; set; } public float Value { get; set; } }Вы можете использовать
whereдля указания диапазона временных меток, а затем использоватьgroupсnullв качестве ключа группировки. MongoDB драйвер переведетMin,MaxиAverageиз анонимного типа в$max,$minи$avgиз синтаксиса Aggregation Frameworkvar 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, можно найти здесь .
EDIT:
(Model)nullтребуется, поскольку запрос должен быть преобразован в$groupС_id, установленным вnull(docs ), так как вы хотите получить один результат с агрегатами. Приведение требуется только для компилятора C#, так как doc имеет типModel.
Агрегирование для этого выполняется в два этапа:
$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;
Comments