LoginSignup
73
64

More than 5 years have passed since last update.

MongoDBのAggregationについて基本的なこと

Posted at

最近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など気になるのがたくさんあるのでもう少し継続してみることにしますね!

73
64
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
73
64