Mongodb项目数值日期(DateTimeOffset)

时间:2017-04-21 22:19:30

标签: c# mongodb mongodb-query datetimeoffset

我使用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],因此我无法使用此字段来获取日期并对其进行格式化。

有什么办法吗?

1 个答案:

答案 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#;)