我使用C#驱动程序在我的收藏中存储DateTimeOffset
字段。
我想按一段时间对值进行分组,即。白天
为此,我做了类似的事情:
db.getCollection('Collection').aggregate([
{
$project:
{
yearMonthDay: { $dateToString: { format: "%Y-%m-%d", date: { <here should go my DateTimeOffsetField> } } }
}
},
{$group: {_id: '$yearMonthDay', count: {$sum:1}}}
])
问题是DateTimeOffset
存储为array[2]
,因此我无法使用此字段来获取日期并对其进行格式化。
有什么办法吗?
答案 0 :(得分:0)
所以我想我想出了如何做到这一点。 DateTimeOffset
被存储为一个包含两个元素的数组:ticks(UTC)和要添加到UTC ticks的分钟数。
为了从这些数据中获取日期,我想我可以存储保存UTC日期时间的附加字段,然后将DateTimeOffset
的分钟数添加到此UTC日期时间。
所以我最终得到了类似的东西:
db.getCollection('State').aggregate([ {
$project: {
yearMonthDay: { $dateToString: {
format: "%Y-%m-%d",
date: { $add: ["$StateDateUTC", {$multiply: [ {$arrayElemAt: ["$StateDateLocal",1]}, 60*1000]} ]}
} },
ticks: "$StateDurationTicks" }
},
{$group: {_id: '$yearMonthDay', count: {$sum:1}, totalTime: {$sum: "$ticks"}}}
])
StateDateUTC
是此附加字段,仅存储UTC日期时间。
StateDateLocal
DateTimeOffset
字段表示为array[2]
,如上所述。
StateDurationTicks
是我要总结的额外持续时间字段。
60*1000
将分钟转换为毫秒,因为我们在mongo中添加Date
和毫秒。
不幸的是,当我直接在mongo c#驱动程序中使用此代码时,有关于json格式化的错误(可能是一个错误?),所以我们需要以BsonDocument
形式重写这个json,看起来像这样:
var aggr = collection.Aggregate();
// [...] bunch of Match()
ProjectionDefinition<State> projection =
new BsonDocument {
{ "yearMonthDay", new BsonDocument {
{ "$dateToString", new BsonDocument {
{ "format", dateFormat },
{ "date", new BsonDocument {
{ "$add", new BsonArray {
{ "$StateDateUTC" },
new BsonDocument { { "$multiply", new BsonArray {
{ 60*1000 },
new BsonDocument { {
"$arrayElemAt", new BsonArray{
{ "$StateDateLocal" },
{ 1 }
}
} }
} } } // multiply
} } // add
} } // date
} } // dateToString
} }, // yearMonthDay
{ "ticks", "$StateDurationTicks" }
};
var projected = aggr.Project<BsonDocument>(projection);
var groupped = projected.Group(new BsonDocument { { "_id", "$yearMonthDay" },
{ "Count", new BsonDocument("$sum", 1) },
{ "Duration", new BsonDocument("$sum", "$ticks") } });
var bsonList = await groupped.ToListAsync();
我认为它有效。
它看起来更像是Lisp而不是C#;)