2013/06/15

Mongodb の Aggregation Framework で月ごとに集計をとる

はじめに

mongodb ので Date Object を含むデータを集計する際に、月ごとで集計をとる方法について説明します。ここでは mongodb version 2.2 で導入された aggregation framework を用います。aggregation framework は非常に柔軟なフレームワークで、SQL に迫るほど強力な集計機能を備えています。map-reduce ほど表現力が豊かではありませんが、ほとんどの集計処理をより手軽に行えます。

早速 aggregation framework を用いて、月ごとに集計をとって見ましょう。

サンプル

まず、mongodb を起動し、mongo shell からサンプルデータを入力しておきます。
> db.revenue.insert({ revenue : 10 , date : ISODate("2013-06-20") })
> db.revenue.insert({ revenue : 5 , date : ISODate("2013-06-30") })
> db.revenue.insert({ revenue : 4 , date : ISODate("2013-05-30") })
> db.revenue.insert({ revenue : 6 , date : ISODate("2013-05-20") })
> db.revenue.insert({ revenue : 3 , date : ISODate("2013-05-10") })
> db.revenue.insert({ revenue : 1 , date : ISODate("2013-04-10") })
> db.revenue.insert({ revenue : 5 , date : ISODate("2013-04-20") })
> db.revenue.insert({ revenue : 2 , date : ISODate("2013-04-30") })
> db.revenue.find()
{ "_id" : ObjectId("51bbbf89d6ac2be7cae104b8"), "revenue" : 20, "date" : ISODate("2013-06-10T00:00:00Z") }
{ "_id" : ObjectId("51bbbfb5d6ac2be7cae104b9"), "revenue" : 10, "date" : ISODate("2013-06-20T00:00:00Z") }
{ "_id" : ObjectId("51bbbfc3d6ac2be7cae104ba"), "revenue" : 5, "date" : ISODate("2013-06-30T00:00:00Z") }
{ "_id" : ObjectId("51bbbfd9d6ac2be7cae104bb"), "revenue" : 4, "date" : ISODate("2013-05-30T00:00:00Z") }
{ "_id" : ObjectId("51bbbfe6d6ac2be7cae104bc"), "revenue" : 6, "date" : ISODate("2013-05-20T00:00:00Z") }
{ "_id" : ObjectId("51bbbfedd6ac2be7cae104bd"), "revenue" : 3, "date" : ISODate("2013-05-10T00:00:00Z") }
{ "_id" : ObjectId("51bbbff7d6ac2be7cae104be"), "revenue" : 1, "date" : ISODate("2013-04-10T00:00:00Z") }
{ "_id" : ObjectId("51bbc000d6ac2be7cae104bf"), "revenue" : 5, "date" : ISODate("2013-04-20T00:00:00Z") }
{ "_id" : ObjectId("51bbc008d6ac2be7cae104c0"), "revenue" : 2, "date" : ISODate("2013-04-30T00:00:00Z") }

これらのデータについて、月ごとの revenue を集計してみましょう。
今回使用する aggreagation framework のオペレータは 以下です。
$project : document を集計しやすくするために整形する(SQL での SELECT に相当)
$month : Date Object から月を示す数値を返す
$year : Date Object から年を示す数値を返す
$group : document を集計するためにグルーピングを行う(SQL での GROUP BY に相当
$sum : 数値を合計する

オペレータ一覧は下記ページにあります。
Aggregation Framework Reference

クエリは以下のようになります。
> db.revenue.aggregate(
  { $project : {
    ym : { 
      year : { $year : "$date" }, 
      month : { $month : "$date" }
    },
    revenue : 1}
  }, 
  { $group : {
    _id : "$ym" , 
    revenue_per_month : { $sum : "$revenue" }
    }
  })

{
 "result" : [
  {
   "_id" : {
    "year" : 2013,
    "month" : 5
   },
   "revenue_per_month" : 13
  },
  {
   "_id" : {
    "year" : 2013,
    "month" : 4
   },
   "revenue_per_month" : 8
  },
  {
   "_id" : {
    "year" : 2013,
    "month" : 6
   },
   "revenue_per_month" : 35
  }
 ],
 "ok" : 1
}

上記クエリについてすこし説明を加えておくと、まず、$project オペレータで Date Objectから年と月を取り出し、集計に使う revenue を抽出しておきます。$project オペレータに続いて、pipeline で $group オペレータを作用させ、実際に集計を行います。

上記で用いたオペレータ以外にも、$sort や $match など便利なオペレータがたくさんありますので、ぜひ試してみてください。

参考文献

MongoDB : Aggregation Framework Reference
SQL to Aggregation Framework Mapping Chart
MongoDBでゆるふわDB体験

0 件のコメント:

コメントを投稿