Docs Menu
Docs Home
/
MongoDBマニュアル
/ / /

$unwind(集計)

項目一覧

  • 定義
  • 互換性
  • 構文
  • 動作
  • 追加リソース
$unwind

入力ドキュメントから配列フィールドを分解して、要素のドキュメントを出力します。各出力ドキュメントは、配列フィールドの値が要素に置き換えられた入力ドキュメントです。

次の環境でホストされる配置には $unwind を使用できます。

  • MongoDB Atlas はクラウドでの MongoDB 配置のためのフルマネージド サービスです

  • MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン

  • MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン

フィールドパス オペランドまたはドキュメント オペランドを渡して、配列フィールドを展開できます。

配列フィールドパスを$unwindに渡すことができます。 この構文を使用する場合、フィールド値が null、欠落、または空の配列である場合、 $unwindはドキュメントを出力しません。

{ $unwind: <field path> }

フィールド パスを指定するときは、フィールド名の前にドル記号$を付け、引用符で囲みます。

バージョン 3.2 で追加

ドキュメントを$unwindに渡して、さまざまな動作オプションを指定できます。

{
$unwind:
{
path: <field path>,
includeArrayIndex: <string>,
preserveNullAndEmptyArrays: <boolean>
}
}
フィールド
タイプ
説明
string

配列フィールドへのフィールドパス。フィールドパスを指定するには、フィールド名の前にドル記号$を付け、引用符で囲みます。

string

任意。要素の配列インデックスを保持する新しいフィールドの名前。名前をドル記号$で始めることはできません。

ブール値

任意。

  • trueの場合、 pathが null、欠落、または空の配列である場合、 $unwindはドキュメントを出力します。

  • false の場合、 path が null か欠落しているか空の配列になっている場合、$unwind ではドキュメントが出力されません。

デフォルト値は false です。

  • オペランドが配列に解決されないが、欠落しているわけでもnull でもなく、または空の配列でもない場合、$unwind はオペランドを単一要素の配列として扱います。

  • オペランドが null か欠落しているか空の配列になっている場合、 $unwind では preserveNullAndEmptyArrays オプションに設定した動作に従います。

入力ドキュメントに存在しないフィールド、またはフィールドが空の配列であるフィールドのパスを指定すると、 $unwindはデフォルトで入力ドキュメントを無視し、その入力ドキュメントのドキュメントを出力しません。

バージョン3.2の新機能: 配列フィールドが欠落しているか null か空の配列になっているドキュメントを出力するには、 preserveNullAndEmptyArraysオプションを使用します。

mongoshでは、次のドキュメントを含むinventoryという名前のサンプル コレクションが作成されます。

db.inventory.insertOne({ "_id" : 1, "item" : "ABC1", sizes: [ "S", "M", "L"] })

次に示す集計では、$unwind ステージを使用して、 sizes 配列にある要素ごとのドキュメントを出力します。

db.inventory.aggregate( [ { $unwind : "$sizes" } ] )

この操作は次の結果を返します。

{ "_id" : 1, "item" : "ABC1", "sizes" : "S" }
{ "_id" : 1, "item" : "ABC1", "sizes" : "M" }
{ "_id" : 1, "item" : "ABC1", "sizes" : "L" }

各ドキュメントは入力ドキュメントと同じですが、sizes フィールドの値が元の sizes 配列の値に置き換えられています。

バージョン 3.2 で追加

mongoshでは、次のドキュメントを含むinventory2という名前のサンプル コレクションが作成されます。

db.inventory2.insertMany([
{ "_id" : 1, "item" : "ABC", price: NumberDecimal("80"), "sizes": [ "S", "M", "L"] },
{ "_id" : 2, "item" : "EFG", price: NumberDecimal("120"), "sizes" : [ ] },
{ "_id" : 3, "item" : "IJK", price: NumberDecimal("160"), "sizes": "M" },
{ "_id" : 4, "item" : "LMN" , price: NumberDecimal("10") },
{ "_id" : 5, "item" : "XYZ", price: NumberDecimal("5.75"), "sizes" : null }
])

次の$unwind操作は同等であり、 sizesフィールドの各要素のドキュメントを返します。 sizesフィールドが配列に解決されず、欠落、値が null、または空の配列でもない場合、 $unwindは配列以外のオペランドを単一要素の配列として扱います。

db.inventory2.aggregate( [ { $unwind: "$sizes" } ] )
db.inventory2.aggregate( [ { $unwind: { path: "$sizes" } } ] )

この操作により、次のドキュメントが返されます。

{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "S" }
{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "M" }
{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "L" }
{ "_id" : 3, "item" : "IJK", "price" : NumberDecimal("160"), "sizes" : "M" }

次の$unwind操作では、 includeArrayIndexオプションを使用して、出力に配列インデックスを含めます。

db.inventory2.aggregate( [
{
$unwind:
{
path: "$sizes",
includeArrayIndex: "arrayIndex"
}
}])

この操作はsizes配列を展開し、 配列インデックスの配列インデックスを新しいarrayIndexフィールドに含めます。 sizesフィールドが配列に解決されず、欠落、値が null、または空の配列でもない場合、 arrayIndexフィールドはnullになります。

{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "S", "arrayIndex" : NumberLong(0) }
{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "M", "arrayIndex" : NumberLong(1) }
{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "L", "arrayIndex" : NumberLong(2) }
{ "_id" : 3, "item" : "IJK", "price" : NumberDecimal("160"), "sizes" : "M", "arrayIndex" : null }

次の$unwind操作ではpreserveNullAndEmptyArraysオプションを使用して、 sizesフィールドが null、欠落、または空の配列であるドキュメントを含めます。

db.inventory2.aggregate( [
{ $unwind: { path: "$sizes", preserveNullAndEmptyArrays: true } }
] )

出力には、sizes フィールドが null、欠落、または空の配列であるドキュメントが含まれます。

{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "S" }
{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "M" }
{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "L" }
{ "_id" : 2, "item" : "EFG", "price" : NumberDecimal("120") }
{ "_id" : 3, "item" : "IJK", "price" : NumberDecimal("160"), "sizes" : "M" }
{ "_id" : 4, "item" : "LMN", "price" : NumberDecimal("10") }
{ "_id" : 5, "item" : "XYZ", "price" : NumberDecimal("5.75"), "sizes" : null }

mongoshでは、次のドキュメントを含むinventory2という名前のサンプル コレクションが作成されます。

db.inventory2.insertMany([
{ "_id" : 1, "item" : "ABC", price: NumberDecimal("80"), "sizes": [ "S", "M", "L"] },
{ "_id" : 2, "item" : "EFG", price: NumberDecimal("120"), "sizes" : [ ] },
{ "_id" : 3, "item" : "IJK", price: NumberDecimal("160"), "sizes": "M" },
{ "_id" : 4, "item" : "LMN" , price: NumberDecimal("10") },
{ "_id" : 5, "item" : "XYZ", price: NumberDecimal("5.75"), "sizes" : null }
])

次のパイプラインでは sizes 配列を展開し、生成されたドキュメントを展開させたサイズ値でグループ化します。

db.inventory2.aggregate( [
// First Stage
{
$unwind: { path: "$sizes", preserveNullAndEmptyArrays: true }
},
// Second Stage
{
$group:
{
_id: "$sizes",
averagePrice: { $avg: "$price" }
}
},
// Third Stage
{
$sort: { "averagePrice": -1 }
}
] )
第 1 ステージ:

$unwindステージでは、 sizes配列の要素ごとに新しいドキュメントが出力されます。 ステージではpreserveNullAndEmptyArraysオプションを使用して、 sizesフィールドが欠落しているか null か空の配列になっているドキュメントを出力に含めます。 このステージでは、次のドキュメントを次のステージに渡します。

{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "S" }
{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "M" }
{ "_id" : 1, "item" : "ABC", "price" : NumberDecimal("80"), "sizes" : "L" }
{ "_id" : 2, "item" : "EFG", "price" : NumberDecimal("120") }
{ "_id" : 3, "item" : "IJK", "price" : NumberDecimal("160"), "sizes" : "M" }
{ "_id" : 4, "item" : "LMN", "price" : NumberDecimal("10") }
{ "_id" : 5, "item" : "XYZ", "price" : NumberDecimal("5.75"), "sizes" : null }
第 2 ステージ:

$groupステージでは、ドキュメントをsizes別にグループ化し、各サイズの平均価格を計算します。このステージでは、次のドキュメントを次のステージに渡します。

{ "_id" : "S", "averagePrice" : NumberDecimal("80") }
{ "_id" : "L", "averagePrice" : NumberDecimal("80") }
{ "_id" : "M", "averagePrice" : NumberDecimal("120") }
{ "_id" : null, "averagePrice" : NumberDecimal("45.25") }
第 3 ステージ:

$sortステージでは、ドキュメントをaveragePriceの降順でソートします この操作では、次の結果を返します。

{ "_id" : "M", "averagePrice" : NumberDecimal("120") }
{ "_id" : "L", "averagePrice" : NumberDecimal("80") }
{ "_id" : "S", "averagePrice" : NumberDecimal("80") }
{ "_id" : null, "averagePrice" : NumberDecimal("45.25") }

Tip

以下も参照してください。

mongoshでは、次のドキュメントを含むsalesという名前のサンプル コレクションが作成されます。

db.sales.insertMany([
{
_id: "1",
"items" : [
{
"name" : "pens",
"tags" : [ "writing", "office", "school", "stationary" ],
"price" : NumberDecimal("12.00"),
"quantity" : NumberInt("5")
},
{
"name" : "envelopes",
"tags" : [ "stationary", "office" ],
"price" : NumberDecimal("19.95"),
"quantity" : NumberInt("8")
}
]
},
{
_id: "2",
"items" : [
{
"name" : "laptop",
"tags" : [ "office", "electronics" ],
"price" : NumberDecimal("800.00"),
"quantity" : NumberInt("1")
},
{
"name" : "notepad",
"tags" : [ "stationary", "school" ],
"price" : NumberDecimal("14.95"),
"quantity" : NumberInt("3")
}
]
}
])

次の操作では、販売された商品をタグごとにグループ化し、タグごとに合計販売額を計算します。

db.sales.aggregate([
// First Stage
{ $unwind: "$items" },
// Second Stage
{ $unwind: "$items.tags" },
// Third Stage
{
$group:
{
_id: "$items.tags",
totalSalesAmount:
{
$sum: { $multiply: [ "$items.price", "$items.quantity" ] }
}
}
}
])
第 1 ステージ

1 つ目の $unwind ステージでは、新しいドキュメントが次のように items 配列の要素ごとに出力されます。

{ "_id" : "1", "items" : { "name" : "pens", "tags" : [ "writing", "office", "school", "stationary" ], "price" : NumberDecimal("12.00"), "quantity" : 5 } }
{ "_id" : "1", "items" : { "name" : "envelopes", "tags" : [ "stationary", "office" ], "price" : NumberDecimal("19.95"), "quantity" : 8 } }
{ "_id" : "2", "items" : { "name" : "laptop", "tags" : [ "office", "electronics" ], "price" : NumberDecimal("800.00"), "quantity" : 1 } }
{ "_id" : "2", "items" : { "name" : "notepad", "tags" : [ "stationary", "school" ], "price" : NumberDecimal("14.95"), "quantity" : 3 } }
第 2 ステージ

2 つ目の $unwind ステージでは、新しいドキュメントが次のように items.tags 配列の要素ごとに出力されます。

{ "_id" : "1", "items" : { "name" : "pens", "tags" : "writing", "price" : NumberDecimal("12.00"), "quantity" : 5 } }
{ "_id" : "1", "items" : { "name" : "pens", "tags" : "office", "price" : NumberDecimal("12.00"), "quantity" : 5 } }
{ "_id" : "1", "items" : { "name" : "pens", "tags" : "school", "price" : NumberDecimal("12.00"), "quantity" : 5 } }
{ "_id" : "1", "items" : { "name" : "pens", "tags" : "stationary", "price" : NumberDecimal("12.00"), "quantity" : 5 } }
{ "_id" : "1", "items" : { "name" : "envelopes", "tags" : "stationary", "price" : NumberDecimal("19.95"), "quantity" : 8 } }
{ "_id" : "1", "items" : { "name" : "envelopes", "tags" : "office", "price" : NumberDecimal("19.95"), "quantity" : 8 } }
{ "_id" : "2", "items" : { "name" : "laptop", "tags" : "office", "price" : NumberDecimal("800.00"), "quantity" : 1 } }
{ "_id" : "2", "items" : { "name" : "laptop", "tags" : "electronics", "price" : NumberDecimal("800.00"), "quantity" : 1 } }
{ "_id" : "2", "items" : { "name" : "notepad", "tags" : "stationary", "price" : NumberDecimal("14.95"), "quantity" : 3 } }
{ "_id" : "2", "items" : { "name" : "notepad", "tags" : "school", "price" : NumberDecimal("14.95"), "quantity" : 3 } }
第 3 ステージ

$groupステージでは、ドキュメントをタグ別にグループ化し、各タグが付いたアイテムの合計売上額を計算します。

{ "_id" : "writing", "totalSalesAmount" : NumberDecimal("60.00") }
{ "_id" : "stationary", "totalSalesAmount" : NumberDecimal("264.45") }
{ "_id" : "electronics", "totalSalesAmount" : NumberDecimal("800.00") }
{ "_id" : "school", "totalSalesAmount" : NumberDecimal("104.85") }
{ "_id" : "office", "totalSalesAmount" : NumberDecimal("1019.60") }

Tip

以下も参照してください。

戻る

$unset