2013-06-01 3 views
2

MongoDB 데이터베이스를 사용하여 응용 프로그램의 분석을 추적합니다. Clojure 응용 프로그램 (clj-time과 Monger 사용)을 작성하여 데이터베이스에서 데이터를 가져옵니다.특정 시간대에 따라 일별 레코드를 그룹화하는 효율적인 방법이 있습니까?

나는

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

각각 다른 device 내 서비스의 다른 사용자를 대표하는 같은 기록을 포함하는 컬렉션이 있습니다. 내가하고 싶은 것은 매일 매일 얼마나 많은 (고유 한) 사용자가 있는지 알아 보는 것입니다. 그러나 "일"이 일광 절약 시간을 고려하여 미국/중부 표준시를 구체적으로 언급하고 싶다는 경고가 있습니다. . (즉, 요구 사항이 아니었다면 난 그냥 다음 $groupdistinct 같은 일을 할 수 있다고 생각.)

여기

내가 뭘했는지의 :

(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 미드 나이트의 목록을 중앙 시간대에서 가져온 다음 Mongo 쿼리를 실행하여 각각의 연속적인 쌍의 중창 사이의 모든 레코드를 찾습니다. 그런 다음 각 일 내에 별개의 device 수를 계산하십시오. 여기

내가이 방법에 대한 좋아하지 않는거야 (난 보통 한 번에 30 일보고) 잘못된 느낌이 매일에 대해 별도의 쿼리를 실행

  1. 을; 이것은 응용 프로그램 측 대신 데이터베이스 측에서 수행해야하는 작업입니다.
  2. device을 구별하는 작업은 데이터베이스에서 수행해야합니다.
  3. 내 서버는 UTC 시간대로 설정되어 있으므로 중부 표준시 자정 이후 자정 이전 인 경우이 목록의 마지막 항목은 항상 0입니다. 이것은 패치하기에 충분히 쉽지만 처음에는 그것을 막을만큼 똑똑한 솔루션을 선호합니다.
  4. 이 전체 기능을 실행하는 데 약 500ms가 걸립니다. 그것은 끔찍한 것이 아닙니다. 저는 쿼리를 실행하는 유일한 사람이고, 하루에 한두 번만 실행합니다.하지만 오랜 시간이 걸리지 않아야하는 것처럼 보입니다.

이 논리를 MongoDB 쿼리에 더 많이 적용 할 수있는 방법이 있습니까?

+1

한 가지 방법은 날짜를 중앙 시간으로 포함하도록 데이터를 수정하는 것입니다. 또는 MapReduce를 작성하여 합계를 계산할 수도 있습니다. 너 그거 해봤 니? – WiredPrairie

답변

1

@WiredPrairie의 제안에 따라 데이터베이스에 추가 할 때 각 레코드에 중부 표준시 날짜가 포함되도록했습니다. 그런 다음 각 날짜의 레코드 수를 수집하기 위해 간단한 $group 쿼리를 사용할 수있었습니다.