公式ページ(aggregate)が難しかったので共有します。
group化した列をカウントする
サンプルデータ
> db.blogtest.find(); { "_id" : ObjectId("5c6…"), "title" : "Node.jsでWebサーバ構築", "access_number" : 1 } { "_id" : ObjectId("5c6…"), "title" : "Node.jsでWebサーバ構築", "access_number" : 3 } { "_id" : ObjectId("5c6…"), "title" : "MongoDBサンプルコード", "access_number" : 2 } { "_id" : ObjectId("5c6…"), "title" : "Node.jsでWebサーバ構築", "access_number" : 1 } { "_id" : ObjectId("5c6…"), "title" : "Node.jsでWebサーバ構築", "access_number" : 3 } { "_id" : ObjectId("5c6…"), "title" : "MongoDBサンプルコード", "access_number" : 2 } { "_id" : ObjectId("5c6…"), "title" : "MongoDBサンプルコード", "access_number" : 0 } { "_id" : ObjectId("5c6…"), "title" : "MongoDB構築", "access_number" : 5 }
db.collection.aggregate()を使用します。
SQLで言うgroup byに相当します。
引数に$group: {_id:”$(列名)”}のような使い方をします。
#{$sum: 1}でgroup化した列をカウントできます。
> db.blogtest.aggregate( { $group : { _id : "$title", "average" : { $avg : "$access_number" }, // _idでgroup化した"title"ごとのデータの平均 "sum" : { $sum : "$access_number" }, // _idでgroup化した"title"ごとのデータの合計 "postNum" : { $sum : 1 } // _idでgroup化したデータの合計(sum:1) }}, {$sort: {"average":-1}} // averageで降順にソート );
// 検索結果 { "_id" : "MongoDB構築", "average" : 5, "sum" : 5, "postNum" : 1 } { "_id" : "MongoDBサンプルコード", "average" : 1.3333333333333333, "sum" : 4, "postNum" : 3 } { "_id" : "Node.jsでWebサーバ構築", "average" : 1.25, "sum" : 5, "postNum" : 4 }
複数の項目でgroup化した列を集計する
同じくdb.collection.aggregate()を使用します。
引数に$group: {_id:”$(列名1)”,”$(列名2)”}のような使い方をします。
サンプルデータ&コード
// DBの中身を確認
> db.blogtest.find() { "_id" : "title" : "Node.jsでWebサーバ構築", "category" : "Node.js", "access_number" : 1 } { "_id" : "title" : "Node.jsでWebサーバ構築", "category" : "Node.js", "access_number" : 3 } { "_id" : "title" : "Node.jsでWebサーバ構築", "category" : "Web", "access_number" : 0 } { "_id" : "title" : "Node.jsでWebサーバ構築", "category" : "Web", "access_number" : 1 } { "_id" : "title" : "MongoDBサンプルコード", "category" : "MongoDB", "access_number" : 1 } { "_id" : "title" : "MongoDB構築", "category" : "MongoDB", "access_number" : 5 } { "_id" : "title" : "MongoDBサンプルコード", "category" : "MongoDB", "access_number" : 2 } { "_id" : "title" : "MongoDBサンプルコード", "category" : "MongoDB", "access_number" : 1 }
// Aggregateコマンドを実行 > db.blogtest.aggregate( ... { $group : ... { ... _id : {"title": "$title","category": "$category"}, ... "max": {$max : "$access_number" } ... } ... });
// 実行結果 { "_id" : { "title" : "MongoDB構築", "category" : "MongoDB" }, "max" : 5 } { "_id" : { "title" : "MongoDBサンプルコード", "category" : "MongoDB" }, "max" : 2 } { "_id" : { "title" : "Node.jsでWebサーバ構築", "category" : "Web" }, "max" : 1 } { "_id" : { "title" : "Node.jsでWebサーバ構築", "category" : "Node.js" }, "max" : 3 } >
group化した列を集計した結果をさらにgroup化する
group化して抽出した検索結果(合計)をさらにgroup化したい場合のサンプルです。
例えば、「カテゴリごとの合計」を取得して、その「平均」を取得するなどの場合です。
引数に$group: {_id:”$(列名1)”,”$(列名2)”},$group: {_id:”$(列名1)”},のような使い方をすることで検索結果をgroup化できます。
サンプルデータ&コード
// DBの中身を確認
> db.blogtest.find(); { "_id" : "date" : "2019/1/10", "title" : "Node.jsでWebサーバ構築", "category" : "Node.js", "access_number" : 1 } { "_id" : "date" : "2019/1/11", "title" : "Node.jsでWebサーバ構築", "category" : "Node.js", "access_number" : 3 } { "_id" : "date" : "2019/2/12", "title" : "Node.jsでWebサーバ構築", "category" : "Web", "access_number" : 0 } { "_id" : "date" : "2019/1/13", "title" : "Node.jsでWebサーバ構築", "category" : "Web", "access_number" : 1 } { "_id" : "date" : "2019/2/10", "title" : "MongoDBサンプルコード", "category" : "MongoDB", "access_number" : 1 } { "_id" : "date" : "2019/2/11", "title" : "MongoDB構築", "category" : "MongoDB", "access_number" : 5 } { "_id" : "date" : "2019/1/12", "title" : "MongoDBサンプルコード", "category" : "MongoDB", "access_number" : 2 } { "_id" : "date" : "2019/1/13", "title" : "MongoDBサンプルコード", "category" : "MongoDB", "access_number" : 1 }
// Aggregateを実行 > db.blogtest.aggregate( ... { $group : ... { ... _id : {"postMonth":{$substr:["$date",5,1]},"title": "$title","category": "$category"}, ... "max": {$max : "$access_number" } ... } ... }, ... { $group : ... { ... _id : {"postMonth": "$_id.postMonth","category": "$_id.category"}, ... "average" : { $avg : "$max"} ... } ... } ... );
// 検索結果 { "_id" : { "postMonth" : "1", "category" : "Node.js" }, "average" : 3 } { "_id" : { "postMonth" : "1", "category" : "Web" }, "average" : 1 } { "_id" : { "postMonth" : "2", "category" : "MongoDB" }, "average" : 3 } { "_id" : { "postMonth" : "2", "category" : "Web" }, "average" : 0 } { "_id" : { "postMonth" : "1", "category" : "MongoDB" }, "average" : 2 }
Queryでエラーが発生した時は
E QUERY [js] SyntaxError: invalid property id @(shell):7:4
@(shell):7:4に注目しましょう。
7列目の左から4つ目に原因があります。
ブログ用サンプル作成ではまってしまいました。invalid property idといいつつ、括弧が足りてなかったとは。。最初にちゃんと場所特定すればよかった。。
MongoDBの使い方まとめに戻る。
自作アプリケーションを作るならさくらのVPS が手軽で使いやすいです。MongoDBは軽いので最低料金プランのVPSでも運用できます。【初めてでも簡単!】VPSの比較ランキングでも紹介しています。
コメントを残す