MongoDBで複数の配列を1つの配列に集約する方法($project活用術)
複数の配列を1つの配列にまとめて集約するには、MongoDBの集計パイプラインで$projectステージを使用します。この記事では、$setUnion・$ifNull・$filterを組み合わせて、複数の配列フィールドを1つの配列に結合し、さらに条件に一致する要素だけを抽出する方法を解説します。
1. サンプルコレクションの作成
まずは、insertOne()メソッドでサンプルドキュメントを登録したコレクションを作成しましょう。
> db.demo119.insertOne(
... {
... "_id": 101,
... "WebDetails": [
... {
... "ImagePath": "/all/image1",
... "isCorrect": "false"
... },
... {
... "ImagePath": "/all/image2",
... "isCorrect": "true"
... }
... ],
... "ClientDetails": [
... {
... "Name": "Chris",
... "isCorrect": "false"
... },
... {
... "Name": "David",
... "isCorrect": "true"
... }
... ]
... }
... );
{ "acknowledged" : true, "insertedId" : 101 }
このコレクションには、画像情報を持つ「WebDetails」と顧客情報を持つ「ClientDetails」という2つの配列フィールドが含まれています。
2. 登録したドキュメントの確認
find()メソッドを使って、コレクション内のすべてのドキュメントを表示してみましょう。
> db.demo119.find();
このクエリを実行すると、次のような出力が得られます。
{
"_id" : 101, "WebDetails" : [
{ "ImagePath" : "/all/image1", "isCorrect" : "false" },
{ "ImagePath" : "/all/image2", "isCorrect" : "true" } ], "ClientDetails" : [
{ "Name" : "Chris", "isCorrect" : "false" }, { "Name" : "David", "isCorrect" : "true" }
]
}3. 複数の配列を1つの配列に集約するクエリ
続いて、「WebDetails」と「ClientDetails」という2つの配列フィールドを1つの配列に集約する集計クエリを見ていきます。
> db.demo119.aggregate([
... { "$project": {
... "AllDetails": {
... "$filter": {
... "input": {
... "$setUnion": [
... { "$ifNull": [ "$WebDetails", [] ] },
... { "$ifNull": [ "$ClientDetails", [] ] }
... ]
... },
... "as": "out",
... "cond": { "$eq": [ "$$out.isCorrect", "false" ] }
... }
... }
... }},
... { "$match": { "AllDetails.0": { "$exists": true } } }
... ])
このパイプラインで使われている各演算子の役割は以下の通りです。
- $project:新しいフィールド「AllDetails」を生成します。
- $setUnion:複数の配列を1つの配列に統合します(重複要素は自動的に除去されます)。
- $ifNull:フィールドが存在しない場合に空の配列「[]」を代わりに返し、エラーを防止します。
- $filter + cond:条件(ここでは isCorrect が "false")に一致する要素のみを抽出します。
- $match:「AllDetails」が空ではない(最初の要素が存在する)ドキュメントだけを結果に出力します。
4. 実行結果
上記の集計クエリを実行すると、次のような結果が得られます。
{ "_id" : 101, "AllDetails" : [ { "ImagePath" : "/all/image1", "isCorrect" : "false" }, { "Name" : "Chris", "isCorrect" : "false" } ] }このように、「WebDetails」と「ClientDetails」の両方から isCorrect が「false」の要素だけが抽出され、「AllDetails」という単一の配列にまとめられていることが確認できます。
$setUnion と $filter を組み合わせる手法は、配列フィールドが増えても同じ要領で拡張できるため、異なる種類のデータを横断的に検索したい場合に非常に便利です。ぜひ実際のプロジェクトでも活用してみてください。
-
MongoDBで配列を持つ1つのドキュメントを新しいコレクションの複数ドキュメントに変換する方法
MongoDBでは、配列フィールドを持つ1つのドキュメントを、配列の各要素に対応する複数のドキュメントとして新しいコレクションに変換できます。この処理には、集計パイプラインのaggregate()と$unwind、そして結果を別のコレクションに出力するための$outを組み合わせて使用します。サンプルコレクションの作成まず、insertOne()メソッドを使ってドキュメントを挿入し、コレクションを作成しましょう。> db.demo757.insertOne( ... { ... id: 101, ... Name: [John, Bob, Chris]
-
MongoDBのaggregateで$groupを使って複数の集計結果を一度に取得する方法
MongoDBでは、$facetと$groupを組み合わせることで、1回のaggregateクエリで複数の集計結果を同時に取得できます。この記事では、実際のコード例を通じてその方法を解説します。サンプルコレクションの作成まず、ドキュメントを含むコレクションを作成しましょう。以下のようにinsertOne()メソッドを使ってデータを挿入します。> db.demo765.insertOne( ... { ... Name:John, ... Category:ComputerScience, ... SubjectName:MongoDB,