最近RailsでMongoDBを使うことがあって、集計処理の部分でちょっと基本的な知識が不足気味な感じがしたので、公式ドキュメントを漁って理解を深めるなどしてみようかと。
http://docs.mongodb.org/manual/meta/aggregation-quick-reference/
#$group
SQLでいうgroup byのようなものを実現する。
こんな感じのドキュメントがあるとして
db.items.insert([{
name: "pencil",
category: "stationery",
price: 105,
stock: 12
},
{
name: "eraser",
category: "stationery",
price: 140,
stock: 5
},
{
name: "ballpoint",
category: "stationery",
price: 110,
stock: 7
}
]);
文具(stationery)の中で最も高価な商品を抽出します。
db.items.aggregate([
{ $group: { _id: "$category", max_price: { $max: "$price" } } }
]);
=> { "_id" : "stationery", "max_price" : 140 }
#$match
これに抽出条件を追加してみます。SQLでいうwhere条件みたいなものですね。
消しゴム(eraser)を除いて、最も高価な商品を抽出します。
db.items.aggregate([
{ $match: { name: { $ne: "eraser"} } },
{ $group: { _id: "$category", max_price: { $max: "$price" } } }
]);
=> { "_id" : "stationery", "max_price" : 110 }
ちなみに、この$match
や$group
というものはpipelineと呼ばれています。
#$project
projection(射影とか投影とか)
出力する項目を指定することが出来る。SQLでいうSELECT col1, col2 〜 みたいな感じ。
db.items.aggregate([
{ $project: { name: 1, stock: 1 } }
]);
=> { "_id" : ObjectId("53b6994517e790c63de53329"), "name" : "pencil", "stock" : 12 }
{ "_id" : ObjectId("53b6994517e790c63de5332a"), "name" : "eraser", "stock" : 5 }
{ "_id" : ObjectId("53b6994517e790c63de5332b"), "name" : "ballpoint", "stock" : 7 }
_id列がいらない場合
db.items.aggregate([
{ $project: { _id: 0, name: 1, stock: 1 } }
]);
=> { "name" : "pencil", "stock" : 12 }
{ "name" : "eraser", "stock" : 5 }
{ "name" : "ballpoint", "stock" : 7 }
一律40円値上げしてみる(price + 40)。
"raised_price"が列別名になる。
db.items.aggregate([
{ $project: { _id: 0, name: 1, raised_price: { $add: ["$price", 40] } } }
]);
=> { "name" : "pencil", "raised_price" : 145 }
{ "name" : "eraser", "raised_price" : 180 }
{ "name" : "ballpoint", "raised_price" : 150 }
単に列別名にするだけにも使える。
db.items.aggregate([
{ $project: { _id: 0, alias_name: "$name" } }
]);
=> { "alias_name" : "pencil" }
{ "alias_name" : "eraser" }
{ "alias_name" : "ballpoint" }
サブドキュメントを含めた形式で返す。
db.items.aggregate([
{ $project: {
_id: 0,
name: 1,
new_item: {
new_price: { $add: ["$price", 40] },
added_stock: { $add: ["$stock", 3] }
}
}}
]);
=>
{ "name" : "pencil", "new_item" : { "new_price" : 145, "added_stock" : 15 } }
{ "name" : "eraser", "new_item" : { "new_price" : 180, "added_stock" : 8 } }
{ "name" : "ballpoint", "new_item" : { "new_price" : 150, "added_stock" : 10 } }
うむむ。少し基本的なところが理解できた。
他にも$unwind
, $redact
, $out
など気になるのがたくさんあるのでもう少し継続してみることにしますね!