MongoDB Aggregateパイプラインの使い方:$unwind・$group・$projectを実例で解説
MongoDB Aggregateパイプラインの基礎:$unwind・$group・$projectの役割
MongoDBの集計(Aggregation)フレームワークでは、複数のステージを連結したパイプラインによってデータの加工・集計を行います。その中でも特に頻繁に使用されるのが、以下の3つのステージです。
- $unwind:入力ドキュメント内の配列フィールドを分解し、配列の各要素ごとに1つのドキュメントを出力します。
- $group:指定された「_id」式に基づいて入力ドキュメントをグループ化し、それぞれのグループごとにドキュメントを出力します。
- $project:要求されたフィールドのみを含むドキュメントを生成し、パイプラインの次のステージへ渡します。
サンプルコレクションの作成
それでは、実際にドキュメントを格納するコレクションを作成してみましょう。ここでは、メールアドレスとユーザー詳細情報(details配列)を持つドキュメントを挿入します。
> db.demo238.insertOne(
... {
... "EmailId" : "John@gmail.com",
... "details" : [
... {
... "Name" : "Bob",
... "isActive" : true
... }
... ]
... }
...);
{
"acknowledged" : true,
"insertedId" : ObjectId("5e4418e3f4cebbeaebec5152")
}
>
> db.demo238.insertOne(
... {
... "EmailId" : "Chris@gmail.com",
... "details" : [
... {
... "Name" : "David"
... }
... ]
... }
...);
{
"acknowledged" : true,
"insertedId" : ObjectId("5e4418e3f4cebbeaebec5153")
}
>
>
> db.demo238.insertOne(
... {
... "EmailId" : "Mike@gmail.com",
... "details" : [
... {
... "Name" : "Carol",
... "isActive" : true
... }
... ]
... }
...);
{
"acknowledged" : true,
"insertedId" : ObjectId("5e4418e4f4cebbeaebec5154")
}
find()メソッドで全ドキュメントを確認する
find()メソッドを使用すると、コレクション内のすべてのドキュメントを表示して内容を確認できます。
> db.demo238.find().pretty();
上記のコマンドを実行すると、以下のような出力が得られます。
{
"_id" : ObjectId("5e4418e3f4cebbeaebec5152"),
"EmailId" : "John@gmail.com",
"details" : [
{
"Name" : "Bob",
"isActive" : true
}
]
}
{
"_id" : ObjectId("5e4418e3f4cebbeaebec5153"),
"EmailId" : "Chris@gmail.com",
"details" : [
{
"Name" : "David"
}
]
}
{
"_id" : ObjectId("5e4418e4f4cebbeaebec5154"),
"EmailId" : "Mike@gmail.com",
"details" : [
{
"Name" : "Carol",
"isActive" : true
}
]
}
$unwindと$groupを組み合わせたAggregateクエリの実装
続いて、MongoDBのaggregateで配列の分解($unwind)とグループ化($group)を組み合わせたクエリを見ていきましょう。
> db.demo238.aggregate(
... [
... { "$match": { "details.isActive": true } },
... { "$unwind": "$details" },
... { "$match": { "details.isActive": true } },
... { "$group": {
... "_id": "$details.Name",
... "active": { "$first": "$_id" }
... }}
... ],
... function(err,result) {
...
... }
...);
このパイプラインでは、最初の$matchで「isActive」がtrueのドキュメントに絞り込み、$unwindでdetails配列を個別のドキュメントへ展開します。その後、再度$matchでアクティブなユーザーのみを抽出し、$groupによってユーザー名(details.Name)ごとにグループ化しています。さらに$first演算子を使うことで、各グループ内で最初に出現した元のドキュメントの「_id」を取得しています。
このクエリを実行すると、以下の出力が得られます。
{ "_id" : "Carol", "active" : ObjectId("5e4418e4f4cebbeaebec5154") }
{ "_id" : "Bob", "active" : ObjectId("5e4418e3f4cebbeaebec5152") }
結果から分かるように、「isActive」がtrueになっているCarolとBobの2人が抽出され、それぞれ元ドキュメントのObjectIdが「active」フィールドとして紐づけられています。一方、DavidのようにisActiveフィールドを持たないドキュメントは、$matchの条件に合致しないため自動的に除外されます。
まとめ
MongoDBのAggregateパイプラインでは、$matchによる絞り込み、$unwindによる配列の分解、$groupによるグループ化を組み合わせることで、ネストされたデータから柔軟に必要な情報を取り出せます。$firstや$sumなどのグループ演算子を活用すれば、より高度な集計処理も簡単に実現できるため、実務でのデータ分析にもぜひ活用してみてください。
-
MongoDBのAggregateでドキュメントと配列要素の平均値を取得する方法
MongoDBでドキュメントのフィールドおよび配列内の各要素の平均値を求めるには、aggregate()メソッドと$groupステージを組み合わせ、平均を計算する$avg演算子を使用します。ここでは、実際にサンプルコレクションを作成しながら、具体的な手順を解説します。 サンプルコレクションの作成 まず、insertOne()メソッドを使ってドキュメントを挿入し、コレクションを作成します。 > db.demo598.insertOne( ... { ... Information:Student, ... &
-
MongoDBのaggregateで$groupを使って複数の集計結果を一度に取得する方法
MongoDBでは、$facetと$groupを組み合わせることで、1回のaggregateクエリで複数の集計結果を同時に取得できます。この記事では、実際のコード例を通じてその方法を解説します。サンプルコレクションの作成まず、ドキュメントを含むコレクションを作成しましょう。以下のようにinsertOne()メソッドを使ってデータを挿入します。> db.demo765.insertOne( ... { ... Name:John, ... Category:ComputerScience, ... SubjectName:MongoDB,