2013-06-01 22 views
2

我正在使用MongoDB數據庫來跟蹤應用程序的分析。我正在編寫一個Clojure應用程序(使用clj-time和Monger)從數據庫中獲取數據。根據特定時區,是否有一種按日期分組記錄的有效方法?

我有一個包含記錄的集合像

{"_id": ObjectId(...), 
timestamp: ISODate("2013-06-01T15:18:37Z"), 
device: "04dbf04b6dc0d0a4fd383967b3dc62f50111e07e"} 

每個不同device代表我公司的服務不同的用戶。我想要做的是找出我每天有多少(獨特)用戶,但是我希望「日」能特別提及美國/中央時區,並將夏令時考慮在內。 (如果這是不是一個要求,我認爲我可以做一些像$group然後distinct。)

這就是我一直在做:

(ns analytics.reporting 
    (:use [monger.core :only [connect! connect set-db! get-db]] 
     monger.operators 
     clj-time.core 
     clj-time.periodic 
     clj-time.format) 
    (:require [monger.collection :as mc])) 

(defn to-central 
    [dt] 
    (from-time-zone dt (time-zone-for-id "America/Chicago"))) 

(defn count-distinct 
    [coll] 
    (count (distinct coll))) 

(defn daily-usage 
    [ndays] 
    (let [midnights (map to-central 
         (reverse (for [offset (map days (range ndays))] 
            (minus (to-central (today-at 0 0)) offset)))) 
     by-day (for [midnight midnights] 
       (mc/find-maps "devices" {:timestamp {$gte midnight $lt (plus midnight (days 1))}})) 
     devices-by-day (map #(map :device %) by-day) 
     distinct-devices-by-day (map count-distinct devices-by-day)] 
    distinct-devices-by-day)) 

如果您無法讀取的Clojure ,這基本上是這樣說的:獲得中央時區最近的n midnights的列表,然後運行Mongo查詢以查找每個連續的中午之間的所有記錄。然後,計算每天內不同的device s的數量。

這裏就是我不喜歡這種方法:

  1. 運行一個單獨的查詢每一天(我一般看30天時間)感覺錯;這是應該在數據庫端而不是應用端完成的。
  2. 計數不同的device也應該由數據庫完成。
  3. 我的服務器設置爲UTC時區,因此如果它是在UTC的午夜之後但在中央時間的午夜之前,則此列表中的最後一個條目將始終爲零。這很容易修補,但我更喜歡一個足夠聰明的解決方案,以防止它擺在首位。
  4. 這整個功能需要約500ms運行。這並不糟糕 - 我是唯一一個運行查詢的人,每天只有一次或兩次 - 但似乎操作不應該花費那麼長時間。

有沒有辦法讓更多這種邏輯進入MongoDB查詢?

+1

一種方法是修改數據以包含日期作爲中央時間。或者,您可能可以編寫MapReduce來計算總計。你嘗試過嗎? – WiredPrairie

回答

1

正如@WiredPrairie所建議的那樣,當我將它添加到數據庫中時,我最終在每條記錄中包含了中心時間日期。然後,我可以使用一個簡單的$group查詢來收集每個日期的記錄數。

相關問題