日付と時間の選択について、情報を取り出すときにデータが選択される必要があるかどうかを考慮しなければなりません。時間外に特定のイベントのインスタンスをカウントしたり、定量化したりするために、reduce関数を使用して、ログの集計または統計収集を実行したい場合、これは特に必要となります。
この例では、日や日付の組み合わせの指定、もしくは時刻の指定による範囲指定でのデータへの問い合わせを含みます。伝統的なリレーショナルデータベースでは、日付型としてテーブルに情報を格納することにより、日付指定もしくは日付の範囲指定の抽出を行うことができます。
map/reduceでは、必要な詳細レベルで個々のコンポーネントを日付として公開することにより、同じようなことを実現できます。たとえば、特定の日々と一致するある期間における特定のログタイプの件数のレポートを取得するために、次のmap()
関数を利用できます:
function(doc, meta) { emit([doc.year, doc.mon, doc.day, doc.logtype], null); }
キーに完全な日付を組み込むと、ビューは特定の日付や特定の日付の範囲で検索することが可能になります。ビューの内容を変更すると、このプロセスをより簡単にできます。たとえば、年/月のみで検索することがあるアプリケーションで必要な場合、日を省略することができます。
そしてビルトイン_count
に対応するreduce()
を使用して、様々なクエリを実行することができます。データ選択の形式なしに、たとえば、個々の日、月、そして年まで集計するためにgroup_level
パラメータを使用することができます。さらに、日付が明示的に出力されるため、特定の月のように、特定の範囲で情報を選択することができます。
endkey=[2010,9,30]&group_level=4&startkey=[2010,9,0]
ここで明示的な日付は、開始と終了キーとして指定されています。group_level
は日付とログタイプによる集計を指定するために必要となります。
これはこのような情報が生成されます:
{"rows":[ {"key":[2010,9,1,"error"],"value":5}, {"key":[2010,9,1,"warning"],"value":10}, {"key":[2010,9,2,"error"],"value":8}, {"key":[2010,9,2,"warning"],"value":9}, {"key":[2010,9,3,"error"],"value":16}, {"key":[2010,9,3,"warning"],"value":8}, {"key":[2010,9,4,"error"],"value":15}, {"key":[2010,9,4,"warning"],"value":11}, {"key":[2010,9,5,"error"],"value":6}, {"key":[2010,9,5,"warning"],"value":12} ] }
より細かく、例えば分または秒まで細かく集計するには、map関数への引数に分や秒を追加することにより実現できます。
function(doc, meta) { emit([doc.year, doc.mon, doc.day, doc.hour, doc.min, doc.logtype], null); }
同じトリックは他の基準に基づいて出力するためにも使用できます。たとえば、曜日、年初からの週数、またはある期間でできます:
function(doc, meta) { if (doc.mon) { var quarter = parseInt((doc.mon - 1)/3,10)+1; emit([doc.year, quarter, doc.logtype], null); } }
より複雑な情報、例えば、指定された日付の特定のログタイプの数を取得するには、
map()
と照合順序を提供するreduce()
のステージを組み合わせることができます。
たとえば、次のmap()
関数を使用することにより、そして日付選択と日付レベルを使用して、出力し、前のように日、月、もしくは年を照合することができます。
function(doc, meta) { emit([doc.year, doc.mon, doc.day], doc.logtype); }
便宜上、日付オブジェクトもしくは文字列から配列に変換するdateToArray()
関数を使用したいかもしれません。たとえば、日付は単一のフィールドとしてドキュメント内に格納されている場合:
function(doc, meta) { emit(dateToArray(doc.date), doc.logtype); }
詳細については、dateToArray()
を参照してください。
次のreduce()
f関数を使用すると、データが出力の単一レコード内で各特定のログタイプ、各日付で照合されます。
function(key, values, rereduce) { var response = {"warning" : 0, "error": 0, "fatal" : 0 }; for(i=0; i<values.length; i++) { if (rereduce) { response.warning = response.warning + values[i].warning; response.error = response.error + values[i].error; response.fatal = response.fatal + values[i].fatal; } else { if (values[i] == "warning") { response.warning++; } if (values[i] == "error" ) { response.error++; } if (values[i] == "fatal" ) { response.fatal++; } } } return response; }
group_level
で2(月での集計)を使用した問い合わせのとき、次の出力が生成されます:
{"rows":[ {"key":[2010,7], "value":{"warning":4,"error":2,"fatal":0}}, {"key":[2010,8], "value":{"warning":4,"error":3,"fatal":0}}, {"key":[2010,9], "value":{"warning":4,"error":6,"fatal":0}}, {"key":[2010,10],"value":{"warning":7,"error":6,"fatal":0}}, {"key":[2010,11],"value":{"warning":5,"error":8,"fatal":0}}, {"key":[2010,12],"value":{"warning":2,"error":2,"fatal":0}}, {"key":[2011,1], "value":{"warning":5,"error":1,"fatal":0}}, {"key":[2011,2], "value":{"warning":3,"error":5,"fatal":0}}, {"key":[2011,3], "value":{"warning":4,"error":4,"fatal":0}}, {"key":[2011,4], "value":{"warning":3,"error":6,"fatal":0}} ] }
入力には各月の各エラータイプの件数を含みます。キー出力は年、月、日付を含むので、特定のグループをまたいだグルーピングや集計をサポートしながらも、ビューも明示的な問い合わせをサポートすることに注意してください。たとえば、次のクエリを使用して、2010/11/15から2011/04/30までの情報をみるためには:
?endkey=[2011,4,30]&group_level=2&startkey=[2010,11,15]
次の出力を生成します:
{"rows":[ {"key":[2010,11],"value":{"warning":1,"error":8,"fatal":0}}, {"key":[2010,12],"value":{"warning":3,"error":4,"fatal":0}}, {"key":[2011,1],"value":{"warning":8,"error":2,"fatal":0}}, {"key":[2011,2],"value":{"warning":4,"error":7,"fatal":0}}, {"key":[2011,3],"value":{"warning":4,"error":4,"fatal":0}}, {"key":[2011,4],"value":{"warning":5,"error":7,"fatal":0}} ] }
ドキュメントデータで様々なビューやクエリを提供するため複数のビューを作成することができることを覚えていてください。上記の例では、warningsbydate
ビューを作成するため、ログタイプの制限されたデータタイプのための特定のビューを作成しました。