2

アプリケーションの分析を追跡するために MongoDB データベースを使用しています。データベースからデータを取得するために、(clj-time と Monger を使用して) Clojure アプリケーションを作成しています。

次のようなレコードを含むコレクションがあります

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

それぞれdeviceが私のサービスの異なるユーザーを表します。私がやりたいことは、私が毎日何人の (一意の) ユーザーを持っているかを調べることですが、「日」は特に米国/中央時間帯を指し、夏時間を考慮したいという注意事項があります. $group(それが要件でなければ、 a のようなことをしてからa を実行できると思います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 個の真夜中のリストを取得し、次に Mongo クエリを実行して、連続する真夜中の各ペアの間のすべてのレコードを検索します。device次に、各日内の個別の の数を数えます。

このアプローチについて私が気に入らない点は次のとおりです。

  1. 日ごとに個別のクエリを実行する (私は通常、一度に 30 日を調べます) のは間違っていると感じます。これは、アプリケーション側ではなくデータベース側で行う必要があります。
  2. 個別deviceの のカウントも、データベースで行う必要があります。
  3. 私のサーバーは UTC タイム ゾーンに設定されているため、UTC では午前 0 時以降、中部時間では午前 0 時より前の場合、このリストの最後のエントリは常にゼロになります。これはパッチを適用するのに十分簡単ですが、そもそもそれを防ぐのに十分なほどスマートなソリューションを望んでいます.
  4. この関数全体の実行には約 500 ミリ秒かかります。それはひどいことではありません — クエリを実行するのは私だけで、1 日に 1 つか 2 回しかありません — しかし、操作にそれほど時間がかからないように思えます。

このロジックをさらに MongoDB クエリに押し込む方法はありますか?

4

1 に答える 1