ポイント: MongoDB $unwindは、ドキュメント内の配列フィールドを分解し、各配列アイテムに対して別々の出力ドキュメントを作成する演算子であり、データの可読性を向上させ、グループ化やソートなどの操作を容易にします。
- $unwindは、複雑なドキュメントを個別のエントリに簡素化します。
- MongoDB 3.2以降は、非配列フィールドを単一要素の配列として処理します。
MongoDB $unwind は、MongoDB での集約を実行するのに役立つツールです。$unwind の使い方を見てみましょう。
MongoDB $unwind とは?
MongoDB $unwind 演算子は、ドキュメント内の配列フィールドを分解し、配列内の各アイテムに対して個別の出力ドキュメントを作成するために使用されます。入力ドキュメントと出力ドキュメントの唯一の違いは、出力ドキュメントでは、配列フィールドの値が入力ドキュメントの配列からの単一のアイテムに置き換えられることです。この例を通して説明します。MongoDB $unwind は、複雑なドキュメントをシンプルなドキュメントに変換し、可読性と理解を高めます。これにより、結果の出力に対してグループ化やソートなどの追加操作を実行することもできます。
$unwind 演算子の基本構文
{ $unwind: "$" }
{$unwind: { path : "$", }}
ここでは、成功した $unwind 操作のためにパスの先頭にドル記号「$」を付ける必要があります。次に、私たちの「vehicledetails」コレクションを使用してシンプルな $unwind 操作を実演します。最初に、コレクションを見てみましょう。
db.vehicledetails.find().pretty()
結果:
次に、$unwind演算子を使用して「model_year」配列フィールドを分解し、各年ごとに別のドキュメントを作成します。
db.vehicledetails.aggregate([{$unwind : "$model_year" }]).pretty()
結果:
上記の出力に示されているように、「model_year」配列内の各アイテムに対して新しいドキュメントが作成されます。
$unwindが非配列フィールドパスでどのように機能するか
MongoDB 3.2以前は、$unwind演算子でパスとして定義された非配列フィールドはエラーを引き起こしていました。MongoDB 3.2以降は、欠落、null、または空の配列に解決されない非配列フィールドは、単一要素配列として扱われます。この次の例では、$unwind演算子が単一要素配列をどのように処理するかを示しています。
db.vehicledetails.aggregate([{$unwind : "$make" }]).pretty()
結果:
ここでは、$unwind操作が「make」フィールドを単一アイテムの配列として考慮するため、単一の出力ドキュメントを正常に作成します。
パスとしての欠落フィールド
$unwind演算子は、指定されたパスが欠落または利用できないフィールドの場合、出力を生成しません。$unwindは入力ドキュメントを無視するため、エラーは発生しません。
db.vehicledetails.aggregate([{$unwind : "$use" }]).pretty()
結果:
上記の操作では、$unwind 演算子に提供されたパスは「use」フィールドです。ただし、入力ドキュメントには「use」フィールドがないため、無視されます。
$unwind 演算子のオプション
$unwind 演算子は、includeArrayIndex とpreserveNullAndEmptyArraysという2つのオプション引数で使用できます。このセクションでは、それぞれのオプションが $unwind 操作の結果にどのように影響するかを示します。再度、オプション引数の機能を示すために、追加のドキュメントを持つ「vehicledetails」コレクションを使用します。
db.vehicledetails.find().pretty()
結果:
「model_year」フィールドで上記のデータセットに対して $unwind 操作を実行すると、出力は5つの結果で構成されます。この例で見てみましょう:
db.vehicledetails.aggregate([{$unwind : "$model_year" }]).pretty()
結果:
includeArrayIndex オプション
includeArrayIndex オプションは、$unwind 操作の出力に配列インデックスを取得するために使用されます。「includeArrayIndex」構文でフィールドを定義することで、各出力ドキュメントの配列インデックスを取得できます。配列フィールドが null の場合、ユーザー定義フィールドに null 値が入ります。空の配列が存在する場合は、その配列内にアイテムがないため無視されます。以下の例では、「model_year」フィールドを使用して $unwind 操作を実行し、ユーザー定義の「vehicleIndex」フィールドを使用して配列インデックスをキャプチャします。
db.vehicledetails.aggregate([{$unwind : {path: "$model_year", includeArrayIndex: "vehicleIndex" }}]).pretty()
結果:
preserveNullAndEmptyArrays オプション
$unwind 操作で「preserveNullAndEmptyArrays」オプションを定義すると、配列フィールドが欠落している、null である、または空の配列であるドキュメントを含めることができます。「preserveNullAndEmptyArrays」オプションは、true または false のような真偽値引数のみを受け取ります。「vehicledetails」コレクション内のドキュメントを使用して「preserveNullAndEmptyArrays」オプションを示しましょう。これにより、「model_year」フィールド内の欠落している、null、または空の配列がすべてキャプチャされます。
db.vehicledetails.aggregate([{$unwind : {path: "$model_year", preserveNullAndEmptyArrays: true}}]).pretty()
結果:
アンワインドされた値でデータをグループ化
MongoDB では、$unwind 操作の結果データセットであるアンワインドされた値を使用して、データセットをさらに変換できます。「vehiclesalesmain」コレクションを使用して、$unwind 演算子と他の関数を組み合わせる方法を示します。
db.vehiclesalesmain.find().pretty()
結果:
次のセクションでは、「colours」配列を使用して $unwind 操作を実行します。また、MongoDB グループおよびソートメソッドを使用して、車両の色に応じた平均価格を取得します。
db.vehiclesalesmain.aggregate([{$unwind: {path: "$colours", preserveNullAndEmptyArrays: true}}, {$group: { _id: "$colours", averagePrice: {$avg: "$price"}}},{$sort: {"averagePrice": -1}}])
結果:
上記の数式をいくつかのステップで簡素化して、プロセスをよりよく理解しましょう。以下に完全なフォーマットされた構文を示します。
db.vehiclesalesmain.aggregate([
{
$unwind: {
path: "$colours",
preserveNullAndEmptyArrays: true
}
},
{
$group: {
_id: "$colours",
averagePrice: {
$avg: "$price"
}
}
},
{
$sort: {
"averagePrice": -1
}
}
])
ステップ 1
最初のステップでは、「vehiclesalesmain」コレクション内のドキュメントが「colours」配列フィールドを使用してアンワインドされます。その後、preserveNullAndEmptyArrays を true に設定して、結果の出力内の欠落している、null、または空の配列をキャプチャします。
db.vehiclesalesmain.aggregate([{$unwind: {path: "$colours", preserveNullAndEmptyArrays: true}}]).pretty()
結果:
ステップ 2
2 番目のステップでは、$unwind 操作からの結果ドキュメントが MongoDB グループメソッドを使用して色でグループ化され、各色の平均価格が計算されます。グループ化構文:
{$group: { _id: "$colours", averagePrice: {$avg: "$price"}}}
完全な構文:
db.vehiclesalesmain.aggregate([{$unwind: {path: "$colours", preserveNullAndEmptyArrays: true}}, {$group: { _id: "$colours", averagePrice: {$avg: "$price"}}}])
結果:
ステップ 3
最後に、グループ化されたデータセットは、MongoDB ソートメソッドを使用して降順にソートされます。ソート構文:
{$sort: {"averagePrice": -1}}])
完全な構文:
db.vehiclesalesmain.aggregate([{$unwind: {path: "$colours", preserveNullAndEmptyArrays: true}}, {$group: { _id: "$colours", averagePrice: {$avg: "$price"}}},{$sort: {"averagePrice": -1}}])
結果:
埋め込まれた配列に対する $unwind の使用
$unwind 操作を埋め込まれた配列に対して実行すると、通常の配列フィールドと同じように機能します。$unwind 操作は、各埋め込まれた配列のアイテムを分解します。「vehicleitems」コレクションを使用して、$unwind 演算子が埋め込まれた配列でどのように機能するかを示します。「vehicleitems」コレクションを見てみましょう。
db.vehicleitems.find().pretty()
結果:
次のセクションでは、上記のドキュメントに対して「items」埋め込まれた配列を使用して $unwind 操作を実行します。
db.vehicleitems.aggregate({$unwind: "$items"}).pretty()
結果:
出力ドキュメントからわかるように、すべての「items」埋め込まれた配列内の各アイテムが個別のアイテムとして分解されています。次の例では、「type」配列を使用して結果データセットをさらに分解できます。分解構文:
{$unwind: "$items"},{$unwind: "$items.type"}
完全な構文:
db.vehicleitems.aggregate([{$unwind: "$items"},{$unwind: "$items.type"},{$project: { _id: 0}}])
クリーンな出力を得るために、プロジェクション演算子を使用して「objectId」フィールドを削除します。結果:
これで MongoDB $unwind チュートリアルは終了です。
関連する読み物
MongoDB ガイド
- MongoDB 概要: MongoDB の開始
- Ubuntu と Mac に MongoDB をインストールする方法
- MongoDB にデータベースを作成する
- MongoDB シェル基本コマンド
- MongoDB Compass: Mongo GUI の使用
- MongoDB ロールベースアクセス制御 (RBAC) の説明
- MongoDB プロジェクションおよびプロジェクション演算子の説明
- MongoDB 集約関数の説明
- MongoDB ソート: sort() メソッドと例
- MongoDB での Push および Pull 演算子の使用
- MongoDB $unwind の使い方
- 23 の一般的な MongoDB クエリ演算子とその使用法
- MongoDB 地理位置クエリの例
- MongoDB トランザクションの紹介
- MongoDB インデックス: 主要なインデックスタイプと管理方法
- 知っておくべき主要な MongoDB コマンド
- MongoDB レプリケーション: 完全な紹介
- MongoDB クラスターのセットアップ方法
- MongoDB シャーディング: 概念、例、およびチュートリアル
- MongoDB Atlas: 管理された MongoDB の設定と使用
- MongoDB を Docker コンテナとして実行する方法
- MongoDB メモリ使用量、管理、および要件
- MongoDB バックアップのための mongodump の使い方
- MongoDB バックアップを復元するための mongorestore の例
- PyMongo の使い方
- MongoDB と NodeJS 用の Mongoose の使い方
- MongoDB チートシート
- MongoDB vs Cassandra: NoSQL データベースの比較
- PostgreSQL vs MongoDB: データベースの比較
- MySQL vs MongoDB: データベースの比較
- MongoDB 認定: 紹介
これらの投稿は私自身のものであり、必ずしもBMCの立場、戦略、または意見を表すものではありません。