定義
互換性
次の環境でホストされる配置には $unwind を使用できます。
- MongoDB Atlas: The fully managed service for MongoDB deployments in the cloud
MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン
MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン
構文
フィールドパス オペランドまたはドキュメント オペランドを渡して、配列フィールドを展開します。
フィールドパス オペランド
$unwind に配列フィールドパスを渡すことができます。この構文では、フィールド値が null、欠落、または空の配列である場合、$unwind はドキュメントを出力しません。
{ $unwind: <field path> }
フィールド パスを指定するときは、フィールド名の前にドル記号$を付け、引用符で囲みます。
オプション付きドキュメント オペランド
ドキュメントを$unwindに渡して、オプションを指定できます。
{ $unwind: { path: <field path>, includeArrayIndex: <string>, preserveNullAndEmptyArrays: <boolean> } }
フィールド | タイプ | 説明 |
|---|---|---|
string | 配列フィールドへのフィールドパス。フィールドパスを指定するには、フィールド名の前にドル記号 | |
string | 任意。要素の配列インデックスを保持する新しいフィールドの名前。名前をドル記号 | |
ブール値 | 任意。
デフォルト値は |
動作
非配列フィールドパス
path の値が配列に変換されない場合、$unwind は次のように動作します。
値が欠落ではなく、
nullでも、空の配列でもない場合、$unwindは値をそのまま使用して単一のドキュメントを出力します。includeArrayIndexが指定されている場合、インデックスは配列入力の場合は0、非配列入力の場合はnullになります。リストの後半のドキュメントのインデックスは0より大きいです。If the value is missing,
null, or an empty array,$unwindfollows the preserveNullAndEmptyArrays option. WhenincludeArrayIndexis specified and the document is preserved, the index isnull.
欠落しているフィールド
入力ドキュメントに存在しないフィールド、またはフィールドが空の配列であるフィールドのパスを指定すると、$unwindはデフォルトで入力ドキュメントを無視し、その入力ドキュメントのドキュメントを出力しません。
To output documents where the array field is missing, null, or an empty array, use the preserveNullAndEmptyArrays option.
例
このページの例では、sample_mflix データセット のデータを使用しています。自己管理型 MongoDB 配置にこのデータセットをロードする方法の詳細については、「サンプル データセットのロード」を参照してください。サンプル データベースに何らかの変更を加えた場合は、今ページの例を実行するには、データベースを削除して再作成する必要がある可能性があります。
配列の展開
次の集計では、$unwind ステージを使用して、Inception 映画ドキュメントの genres 配列にある要素ごとのドキュメントを出力します。
db.movies.aggregate( [ { $match: { title: "Inception" } }, { $project: { _id: 0, title: 1, genres: 1 } }, { $unwind: "$genres" } ] )
[ { genres: 'Action', title: 'Inception' }, { genres: 'Mystery', title: 'Inception' }, { genres: 'Sci-Fi', title: 'Inception' } ]
各出力ドキュメントは入力ドキュメントと同じですが、genres フィールドの値が元の genres 配列の単一の要素に置き換えられています。
欠落値または配列以外の値
次の集計では、4 つの映画ドキュメントとともに $unwind ステージを使用しています。2 つのドキュメント ("La porta del cielo" と "Neecha Nagar") には genres フィールドがありません。
db.movies.aggregate( [ { $match: { title: { $in: [ "Inception", "Brave", "La porta del cielo", "Neecha Nagar" ] } } }, { $project: { _id: 0, title: 1, genres: 1 } }, { $unwind: { path: "$genres" } } ] )
[ { genres: 'Animation', title: 'Brave' }, { genres: 'Adventure', title: 'Brave' }, { genres: 'Comedy', title: 'Brave' }, { genres: 'Action', title: 'Inception' }, { genres: 'Mystery', title: 'Inception' }, { genres: 'Sci-Fi', title: 'Inception' } ]
"Brave"および"Inception"ドキュメントでは、genresは入力された配列です。$unwindは各要素のドキュメントを返します。"La porta del cielo"と"Neecha Nagar"のドキュメントにはgenresフィールドがないため、$unwindはそれらのドキュメントを返しません。
注意
{ path: <FIELD> } 構文は任意です。次の$unwind操作は同等です。
db.<COLLECTION>.aggregate( [ { $unwind: "<FIELD>" } ] )
db.<COLLECTION>.aggregate( [ { $unwind: { path: "<FIELD>" } } ] )
preserveNullAndEmptyArrays および includeArrayIndex
The preserveNullAndEmptyArrays and includeArrayIndex examples use documents from the sample_mflix.movies collection.
preserveNullAndEmptyArrays
The following $unwind operation uses the preserveNullAndEmptyArrays option to include documents whose genres field is missing.
db.movies.aggregate( [ { $match: { title: { $in: [ "Inception", "Brave", "La porta del cielo", "Neecha Nagar" ] } } }, { $project: { _id: 0, title: 1, genres: 1 } }, { $unwind: { path: "$genres", preserveNullAndEmptyArrays: true } } ] )
[ { title: 'La porta del cielo' }, { title: 'Neecha Nagar' }, { genres: 'Animation', title: 'Brave' }, { genres: 'Adventure', title: 'Brave' }, { genres: 'Comedy', title: 'Brave' }, { genres: 'Action', title: 'Inception' }, { genres: 'Mystery', title: 'Inception' }, { genres: 'Sci-Fi', title: 'Inception' } ]
includeArrayIndex
The following $unwind operation uses the includeArrayIndex option to include the array index in the output.
db.movies.aggregate( [ { $match: { title: "Inception" } }, { $project: { _id: 0, title: 1, genres: 1 } }, { $unwind: { path: "$genres", includeArrayIndex: "genreIndex" } } ] )
[ { genres: 'Action', title: 'Inception', genreIndex: Long('0') }, { genres: 'Mystery', title: 'Inception', genreIndex: Long('1') }, { genres: 'Sci-Fi', title: 'Inception', genreIndex: Long('2') } ]
展開された値によるグループ化
次のパイプラインでは genres 配列を展開し、生成されたドキュメントをジャンルごとにグループ化して、各ジャンルの映画数をカウントします。
db.movies.aggregate( [ // First Stage { $match: { title: { $in: [ "The Dark Knight", "Inception", "Interstellar", "Brave" ] } } }, // Second Stage { $project: { _id: 0, title: 1, genres: 1 } }, // Third Stage { $unwind: "$genres" }, // Fourth Stage { $group: { _id: "$genres", movieCount: { $sum: 1 } } }, // Fifth Stage { $sort: { movieCount: -1 } } ] )
[ { _id: 'Adventure', movieCount: 2 }, { _id: 'Action', movieCount: 2 }, { _id: 'Drama', movieCount: 2 }, { _id: 'Sci-Fi', movieCount: 2 }, { _id: 'Crime', movieCount: 1 }, { _id: 'Animation', movieCount: 1 }, { _id: 'Comedy', movieCount: 1 }, { _id: 'Mystery', movieCount: 1 } ]
複数配列フィールドの展開
単一のパイプラインで $unwind を複数回適用して、複数の配列フィールドを含むドキュメントを展開できます。次の操作では、genres 配列を展開してから cast 配列を展開して、ジャンルと俳優の組み合わせごとにフラットなドキュメントを作成し、ジャンルごとにグループ化して各ジャンルのキャスト出演の合計をカウントします。
db.movies.aggregate( [ // First Stage { $match: { title: { $in: [ "Inception", "The Dark Knight", "Interstellar" ] } } }, // Second Stage { $project: { _id: 0, title: 1, genres: 1, cast: 1 } }, // Third Stage { $unwind: "$genres" }, // Fourth Stage { $unwind: "$cast" }, // Fifth Stage { $group: { _id: "$genres", castAppearances: { $sum: 1 } } } ] )
[ { _id: 'Adventure', castAppearances: 4 }, { _id: 'Crime', castAppearances: 4 }, { _id: 'Action', castAppearances: 8 }, { _id: 'Drama', castAppearances: 8 }, { _id: 'Mystery', castAppearances: 4 }, { _id: 'Sci-Fi', castAppearances: 8 } ]
このページのC#の例では、Atlasサンプルデータセット の sample_mflixデータベースを使用します。MongoDB Atlasクラスターを無料で作成して、サンプルデータセットをロードする方法については、 MongoDB .NET/ C#ドライバーのドキュメントの「 開始 」を参照してください。
次の Movie クラスは、sample_mflix.movies コレクション内のドキュメントをモデル化します。
public class Movie { public ObjectId Id { get; set; } public int Runtime { get; set; } public string Title { get; set; } public string Rated { get; set; } public List<string> Genres { get; set; } public string Plot { get; set; } public ImdbData Imdb { get; set; } public int Year { get; set; } public int Index { get; set; } public string[] Comments { get; set; } [] public DateTime LastUpdated { get; set; } }
注意
パスカルケースの ConventionPack
このページのC# クラスはプロパティ名にパスカルケースを使用していますが、MongoDB コレクションのフィールド名はキャメルケースを使用しています。この違いを考慮するために、アプリケーションが起動する際に次のコードを使用してConventionPackを登録してください。
var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() }; ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);
MongoDB .NET/ C#ドライバーを使用して$unwind ステージを集計パイプラインに追加するには、 PipelineDefinitionオブジェクトで Unwind() メソッドを呼び出します。
次の例では、各入力 Movieドキュメントの Genresフィールドを反復処理するパイプラインステージを作成しています。ステージは、Genresフィールドの各値に対して新しい Movieドキュメントを作成し、その Genresフィールドに入力ドキュメントの Genres 値を入力します。
var pipeline = new EmptyPipelineDefinition<Movie>() .Unwind(m => m.Genres);
AggregateUnwindOptions オブジェクトを使用して、Unwind() メソッドの動作をカスタマイズできます。
次の例では、前の例と同じ操作を実行しますが、次のオプションも含まれています。
PreserveNullAndEmptyArraysを指定すると、Genresフィールドに空の配列が含まれるドキュメントが出力に含まれるようになります。IncludeArrayIndexオプションは、各出力ドキュメントにIndexという名前の新しいフィールドを追加します。このフィールドの値は、入力ドキュメントのGenres配列内のGenresフィールドの値の配列インデックスです。
var pipeline = new EmptyPipelineDefinition<Movie>() .Unwind(m => m.Genres, new AggregateUnwindOptions<Movie>() { PreserveNullAndEmptyArrays = true, IncludeArrayIndex = new ExpressionFieldDefinition<Movie, int>( m => m.Index) });
このページのNode.js の例では、Atlasサンプルデータセット の sample_mflixデータベースを使用します。無料のMongoDB Atlas cluster を作成し、サンプルデータセットをロードする方法については、 MongoDB Node.jsドライバーのドキュメントの開始を参照してください。
MongoDB Node.jsドライバーを使用して $unwind ステージを集計パイプラインに追加するには、パイプラインオブジェクトで $unwind 演算子を使用します。
次の例では、各入力 movieドキュメントの genresフィールドを反復処理するパイプラインステージを作成しています。ステージは、genresフィールドの各値に対して新しい movieドキュメントを作成し、その genresフィールドに入力ドキュメントの genres 値を入力します。次に、この例では集計パイプラインを実行します。
const pipeline = [{ $unwind: "$genres" }]; const cursor = collection.aggregate(pipeline); return cursor;
$unwind メソッドの動作をカスタマイズできます。次の例では、前の例と同じ操作を実行しますが、次のオプションも含まれています。
preserveNullAndEmptyArraysを指定すると、genresフィールドに空の配列が含まれるドキュメントが出力に含まれるようになります。includeArrayIndex各出力ドキュメントにindexという名前の新しいフィールドを追加します。フィールドには、入力ドキュメントのgenresフィールド内のgenres値の配列インデックスが含まれます。
const pipeline = [ { $unwind: { path: "$genres", preserveNullAndEmptyArrays: true, includeArrayIndex: "index" } } ]; const cursor = collection.aggregate(pipeline); return cursor;
詳細
関連するステージと式については、$group、$sum、$sort、および$multiplyを参照してください。
完全な例については、「配列とグループ データの展開」チュートリアルを参照してください。