2015-11-12 55 views
0

我有一個MongoDB分析樣式的集合。它包含帶有timestamp字段和各種數據的文檔。現在我想通過一個粒度參數來獲得一段時間的文檔數量。MongoDB聚合:具有粒度的時間序列

我目前使用這樣的聚合框架(假設粒度DAY):

db.collection.aggregate([{ 
    $match: { 
    timestamp: { 
     $gte: start_time, 
     $lt: end_time 
    } 
    } 
}, { 
    $group: { 
    _id: { 
     year: { $year: '$timestamp' }, 
     month: { $month: '$timestamp' }, 
     day: { $dayOfMonth: '$timestamp' } 
    }, 
    count: { $sum: 1 } 
    } 
}, { 
    $sort: { 
    _id: 1 
    } 
}]) 

這樣,我有每天count值。 問題是count將取決於計算$dayOfMonth部分時使用的時區(每個count從00:00:000 UTC到UTC:23:59:999)。

我希望能夠實現這一點,而不依賴於時區,但依靠start_time。例如,如果我在UTC時間07:00使用start_time,則我將在UTC時間07:00到第二天07:00 UTC的每一天獲得count s。

TL; DR:我想是這樣的:https://dev.twitter.com/ads/reference/get/stats/accounts/%3Aaccount_id/campaigns

關於如何執行此任何想法?

+0

不知道我明白你的意思取決於時間戳。 Mongo將所有日期存儲爲UTC,因此所有內容都位於同一時區。 –

+0

日期存儲爲UTC,因此如果使用$ dayOfMonth聚合運算符,則會獲得UTC日期。現在,如果你想在不同的時區dayOfMonth,你不能。 更一般地說,我想獲得24小時間隔的計數值(不依賴於任何時區,例如從昨天凌晨1:30到今天凌晨1:30)。 – Owumaro

回答

0

我發現了一個很好的解決方案。這不是很自然,但無論如何。

這個想法是基於startDate和行的日期來計算「標準化」日期。我使用startDate上的$mod運算符來獲取毫秒+秒+小時(對於DAY粒度),然後使用$subtract從該行的日期中減去它。

這裏是一個例子,每天粒度:

var startDate = ISODate("2015-08-25 13:30:00.000Z") 
var endDate = ISODate("2015-08-27 13:30:00.000Z") 

db.collection.aggregate([{ 
    $match: { 
     timestamp: { 
     $gte: startDate, 
     $lt: endDate 
    } 
}, { 
    $project: { 
    timestamp_normalized: { 
     $subtract: [ 
     "$timestamp", 
     { 
      $mod: [ 
      { "$subtract": [ startDate, new Date("1970-01-01") ] }, 
      1000 * 60 * 60 * 24 
      ] 
     } 
     ] 
    } 
    } 
}, { 
    // now $group with $dayOfMonth 
}]) 

$mod部分之後00:00 UTC計算的startDate的小時+秒+毫秒,以毫秒爲單位。

$subtract從原始時間戳中檢索這些毫秒。

現在我可以用$dayOfMonth經營者本人的normalized_timestamp場拿到一天,如果我們考慮從13:30間隔13:30第二天,用$group獲得計數值這些區間。

編輯:它來計算,以創建查詢之前從時間戳移除正常化的價值更簡單了,使用:

(startDate - new Date(0)) % (1000 * 60 * 60 * 24)

(每天粒度)

然後減去直接從timestamp這個值而不是使用$mod