2013-03-20 189 views
0

我想在Mongo中按日期聚合數據,但我不能完全實現我想要的。 現在,我使用的是這樣的:日期聚合框架

db.aggregData.aggregate({ $group: {_id: "$Date".toString(), 
            tweets: { $sum: "$CrawledTweets"} } }, 
         { $match:{ _id: {$gte: ISODate("2013-03-19T12:31:00.247Z") }}}, 
         { $sort: {Date:-1} } 
         ) 

它的結果與此:

"result" : [ 
       { 
         "_id" : ISODate("2013-03-19T12:50:00.641Z"), 
         "tweets" : 114 
       }, 
       { 
         "_id" : ISODate("2013-03-19T12:45:00.631Z"), 
         "tweets" : 114 
       }, 
       { 
         "_id" : ISODate("2013-03-19T12:55:00.640Z"), 
         "tweets" : 123 
       }, 
       { 
         "_id" : ISODate("2013-03-19T12:40:00.628Z"), 
         "tweets" : 91 
        }, 
       { 
         "_id" : ISODate("2013-03-19T12:31:00.253Z"), 
         "tweets" : 43 
       }, 
       { 
         "_id" : ISODate("2013-03-19T13:20:00.652Z"), 
         "tweets" : 125 
       }, 
       { 
         "_id" : ISODate("2013-03-19T12:31:00.252Z"), 
         "tweets" : 30 
       } 
], 
     "ok" : 1 

這似乎做的工作,但進一步的檢查,我們看到有重複:
ISODate(「2013-03-19T12:31:00.253Z」)和ISODate(「2013-03-19T12:31:00.252Z」)。
唯一改變的是Z之前的最後一位。

所以這裏是我的問題。這部分是什麼?我怎麼能在彙總中忽略它呢?

預先感謝您。

編輯:我想聚合到日期,所以全年/月/日+小時和分鐘。其餘的我都不在乎。

編輯:我在mongolab分貝,所以我在2.2

嗯,我做到了另一種方式:我救我所有的日期爲0秒/毫秒所以我可以保持一個簡單的彙總,沒有多一點的代碼服務器端,感謝moment.js

回答

6

您正試圖聚合的「整個」日期,換句話說,從ISODate()的時間,對吧?有幾種方法可以做到這一點,我在博客上詳細描述了他們的帖子

Stupid Date Tricks with Aggregation Framework

你可以看到完整的一步一步的細分那裏,但概括你有兩個選擇:

  • ,如果你不關心聚合通值是一個ISODate()那麼你可以使用{$year},{$month}{$dayOfMonth}運營商在{$project}階段只抽出YMD然後{$ group}就可以了。

  • 如果你關心的分組通值停留在ISODate您可以在{$project}階段{$subtract}時間的一部分,並留下ISODate()型 - 需要注意的是,這種方法需要的MongoDB 2.4 (just released)增加了對日期運算的支持和$millisecond運營商(請參閱博文中的確切代碼)。

這裏可能是你想要什麼:

db.aggregData.aggregate([ 
    { 
    $project:{ 
     CrawledTweets: 1, 
     newDate: { 
      year:{$year:"$Date"}, 
      month: {$month:"$Date"}, 
      day: {$dayOfMonth:"$Date"}, 
      hour: {$hour: "$Date"}, 
      min: {$minute: "$Date"} 
     } 
    } 
    }, 
    { 
    $group: { 
     _id: "$newDate", 
     tweets: { $sum: "$CrawledTweets"} 
    } 
    } 
]) 
+0

謝謝,我會讀。我應該說,但我想按日期彙總,所以全年/月/日+小時和分鐘。其餘的我都不在乎。 – Simon 2013-03-20 16:42:46

+0

小時和分鐘意味着您按分鐘進行彙總 - 但將任意一條路徑擴展到所需的路徑很簡單。就像我說的那樣,如果你使用的是2.2,那麼使用第一種方法{$ project:{year:{$ year:「$ Date」},month:{$ month:「$ Date」}等)已經抓住2.4我推薦在博客文章中使用{$ subtract}來擺脫$毫秒部分。 – 2013-03-20 16:57:00

+0

我真的不明白這是如何工作的。我不能重現這個例子,並使其工作。 – Simon 2013-03-21 09:26:12

1

並非一名專家蒙戈和不知道你的數據庫字段我會想出這樣的事情。也許你可以建立在此:

db.aggregData.aggregate(
{ 
    $project:{ 
     CrawledTweets: 1, 
     groupedTime: { 
      year:{$year:"$_id"}, 
      month: {$month:"$_id"}, 
      day: {$dayOfMonth:"$_id"}, 
      hour: {$hour: "$_id"}, 
      min: {$minute: "$_id"} 
     } 
    } 
}, 
{ 
    $group: { 
     _id: { groupedTime: "$CrawledTweets" }, 
     tweets: { $sum: "$tweets"} 
    } 
} 
) 
+0

我得到了一個錯誤,即$ min,不存在和$分鐘,我有「errmsg」:「異常:不能從BSON類型OID轉換爲日期」。感謝無論如何男人:) – Simon 2013-03-21 13:19:18

+0

你可以把輸入記錄到你的問題?如果我們知道字段/類型,找到解決方案更容易。 – pitseeker 2013-03-21 14:33:18

+1

$ min不存在,但有$微型操作員。另外,他的日期存儲在「日期」字段中,而不是_id。 – 2013-03-21 23:22:36