4

Webサービスからいくつかの統計を収集し、それをコレクションに保存しています。データは次のようになります(ただし、フィールドが多くなります)。

{"downloads": 30, "dt": "2010-02-17T16:56:34.163000"}
{"downloads": 30, "dt": "2010-02-17T17:56:34.163000"}
{"downloads": 30, "dt": "2010-02-17T18:56:34.163000"}
{"downloads": 30, "dt": "2010-02-17T19:56:34.163000"}
{"downloads": 30, "dt": "2010-02-17T20:56:34.163000"}
{…}
{"downloads": 30, "dt": "2010-02-18T17:56:34.163000"}
{"downloads": 30, "dt": "2010-02-18T18:56:34.163000"}
{"downloads": 30, "dt": "2010-02-18T19:56:34.163000"}
{"downloads": 30, "dt": "2010-02-18T20:56:34.163000"}

誰かが過去30日間の毎日の数を要求した場合、それは(この例では)「ダウンロード」prの最大量を意味します。日。これがその日の最後の記録です。

を使用するcollection.find({"dt": {"$gt": datetime_obj_30_days_ago}})ことで、もちろんすべての行を取得しますが、これはあまり適切ではありません。だから私は与えられた期間の一日の最後だけを返す方法を探しています。

それが道かもしれないと言われgroup()ましたが、この場合にそれを機能させる方法を完全に理解することはできません。

ヒント、ポインタをいただければ幸いです。

4

1 に答える 1

1

groupを使用してこれを行うことができます。あなたの例では、datetimeフィールドのdateコンポーネントのみが必要なため、キーを計算するためのjavascript関数(およびreduce関数)を提供する必要があります。これは機能するはずです:

db.coll.group(
    key='function(doc) { return {"dt": doc.dt.toDateString()} }',
    condition={'dt': {'$gt': datetime_obj_30_days_ago}},
    initial={'downloads': 0},
    reduce='function(curr, prev) { prev.downloads = Math.max(curr.downloads, prev.downloads) }'
)

クライアントではなくサーバー上で、先月の線形スキャンを実行することに注意してください。毎日の最大値を個別に選択するだけの方が速い可能性があります。

于 2010-02-19T04:20:06.683 に答える