MongoDBのaggregateで$groupを使って複数の集計結果を一度に取得する方法
MongoDBでは、$facetと$groupを組み合わせることで、1回のaggregateクエリで複数の集計結果を同時に取得できます。この記事では、実際のコード例を通じてその方法を解説します。
サンプルコレクションの作成
まず、ドキュメントを含むコレクションを作成しましょう。以下のようにinsertOne()メソッドを使ってデータを挿入します。
> db.demo765.insertOne(
... {
... Name:"John",
... "Category":"ComputerScience",
... "SubjectName":"MongoDB",
... "Marks":75
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5eb054525637cd592b2a4b01")
}
>
> db.demo765.insertOne(
... {
... Name:"John",
... "Category":"ComputerScience",
... "SubjectName":"MySQL",
... "Marks":85
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5eb054525637cd592b2a4b02")
}
> db.demo765.insertOne(
... {
... Name:"Chris",
... "Category":"10th",
... "SubjectName":"Math",
... "Marks":98
... }
... );
{
"acknowledged" : true,
"insertedId" : ObjectId("5eb054535637cd592b2a4b03")
}登録したドキュメントの確認
find()メソッドを使って、コレクション内のすべてのドキュメントを表示します。
> db.demo765.find();
実行すると、以下のような出力が得られます。
{ "_id" : ObjectId("5eb054525637cd592b2a4b01"), "Name" : "John", "Category" : "ComputerScience", "SubjectName" : "MongoDB", "Marks" : 75 }
{ "_id" : ObjectId("5eb054525637cd592b2a4b02"), "Name" : "John", "Category" : "ComputerScience", "SubjectName" : "MySQL", "Marks" : 85 }
{ "_id" : ObjectId("5eb054535637cd592b2a4b03"), "Name" : "Chris", "Category" : "10th", "SubjectName" : "Math", "Marks" : 98 }$facetと$groupによる複数集計のクエリ
ここからが本題です。$facetステージを使うと、同じ入力ドキュメントに対して複数の集計パイプラインを並列に実行できます。以下の例では、「名前ごとの合計点」と「カテゴリごとの合計点」という2種類のグループ化結果を1回のクエリで取得しています。
> db.demo765.aggregate([
... { "$facet": {
... "ListOfName": [
... { "$group": {
... "_id": "$Name",
... "Marks": { "$sum": "$Marks" }
... }},
... { "$project": {
... "_id": false,
... "Name": "$_id",
... "Marks": 1
... }}
... ],
... "ListOfCategory": [
... { "$group": {
... "_id": "$Category",
... "Marks": { "$sum": "$Marks" }
... }},
... { "$project": {
... "_id": false,
... "Category": "$_id",
... "Marks": 1
... }}
... ]
... }}
... ]).pretty()実行結果
上記のクエリを実行すると、次のような出力が得られます。
{
"ListOfName" : [
{
"Marks" : 98,
"Name" : "Chris"
},
{
"Marks" : 160,
"Name" : "John"
}
],
"ListOfCategory" : [
{
"Marks" : 98,
"Category" : "10th"
},
{
"Marks" : 160,
"Category" : "ComputerScience"
}
]
}ポイント解説
- $facet: 同じドキュメントセットに対して複数のサブパイプラインを適用でき、それぞれの結果を別々のフィールドとして返します。
- $group: 指定したキー(ここでは
NameやCategory)でドキュメントをグループ化し、$sum演算子でMarksの合計を算出しています。 - $project:
_idフィールドを非表示にし、グループ化キーを読みやすいフィールド名(NameやCategory)に変換しています。
このように$facetを活用すれば、複数回クエリを発行することなく、さまざまな切り口での集計結果を効率的に1回のリクエストで取得できます。ダッシュボードやレポート生成など、多角的な集計が必要なシーンで特に有用なテクニックです。
-
【MongoDB】集計パイプラインの$groupを使って日付ごとにデータをグループ化する方法
MongoDBで日付ごとにドキュメントをグループ化したい場合は、aggregate()メソッド内で$group演算子を使用します。本記事では、サンプルコードを交えながら、コレクションの作成から日付単位でのグループ化までの一連の手順をわかりやすく解説します。1. サンプルコレクションの作成まず、日付情報を含むドキュメントを格納するコレクションを用意しましょう。以下の例では、db.demo657というコレクションに対して、id、Name、DueDate(ISODate形式)の各フィールドを持つドキュメントを、insertOne()メソッドで3件挿入しています。> db.demo657.ins
-
MongoDBのアグリゲーションで$redact演算子を使う方法
$redact演算子とはMongoDBの$redactステージは、ドキュメント自体に格納されている情報に基づいて、各ドキュメントの内容を制限(フィルタリング)するための機能です。アグリゲーションフレームワークでは、$cond演算子を$redactと組み合わせることで、条件に応じてドキュメントを保持($$KEEP)するか除外($$PRUNE)するかを柔軟に制御できます。ここでは、実際のコード例を通して、$redactの基本的な使い方を見ていきましょう。サンプルコレクションの作成まず、insertOne()メソッドを使って、複数のドキュメントを含むコレクションを作成します。> db.demo