定義
互換性
次の環境でホストされる配置には $sort を使用できます。
- MongoDB Atlas はクラウドでの MongoDB 配置のための完全管理サービスです
MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン
MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン
構文
$sort の形式は次のとおりです。
{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }
$sort は、ソートするフィールドとそのソート順序を指定するドキュメントを取ります。 <sort order> には次のいずれかの値を指定できます。
値 | 説明 |
|---|---|
| 昇順にソートします。 |
| 降順にソートします。 |
| 計算された |
複数のフィールドでソートする場合、$sort は左から右にソート順序を評価します。ドキュメントは最初に <field1> によってソートされ、次に同じ <field1> 値を持つドキュメントが <field2> によってソートされます。
動作
パフォーマンス
$sort はブロッキング ステージであり、パイプラインはデータを処理する前にすべての入力データが検索されるまで待機します。ブロッキング ステージは、複数のステージを持つパイプラインの並列処理を減らすため、パフォーマンスを低下させる可能性があります。ブロッキング ステージでは、大規模なデータセットに対して大量のメモリが使用される場合もあります。
制限
最大 32 個のキーでソートすることができます。
重複するフィールドを含むソート パターンを指定すると、エラーが発生します。
ソートの一貫性
MongoDB では、コレクション内のドキュメントを特定の順序で保存することはありません。重複する値を含むフィールドでソートする場合、それらの値を含むドキュメントは任意の順序で返されます。
$sort 操作は「安定ソート」ではありません。これはソートキーと同等のドキュメントが、入力時と同じ相対的順序で出力に残ることは保証されないという意味です。
ソート条件で指定されたフィールドが2つのドキュメントに存在しない場合、それらがソートされる値は同じです。2つのドキュメントは、任意の順序で返される可能性があります。
一貫したソート順序が必要な場合は、一意の値を含むフィールドを少なくとも 1 つ含めてソートしてください。これを保証する最も簡単な方法は、_idフィールドをソートのクエリに含めることです。
sample_mflixサンプルデータセットの moviesコレクションについて考えてみます。次のコマンドは、1925 または 1926 でリリースされた映画を year で昇順にソートします。
db.movies.aggregate( [ { $match: { year: { $in: [ 1925, 1926 ] } } }, { $sort: { year: 1 } }, { $project: { _id: 0, title: 1, year: 1 } } ] )
yearフィールドには 1925 と 1926 の値が重複しているため、同じ値を持つドキュメントの実行によってソートが異なる場合があります。例、前のコマンドを 2 回実行すると生成される順序が異なります。
[ { title: "Clash of the Wolves", year: 1925 }, { title: "Lady Windermere's Fan", year: 1925 }, { title: "Grass: A Nation's Battle for Life", year: 1925 }, { title: "Beau Geste", year: 1926 }, { title: "The Black Pirate", year: 1926 }, { title: "Ella Cinders", year: 1926 }, { title: "For Heaven's Sake", year: 1926 }, { title: "The Son of the Sheik", year: 1926 }, { title: "The Strong Man", year: 1926 } ]
[ { title: "Lady Windermere's Fan", year: 1925 }, { title: "Grass: A Nation's Battle for Life", year: 1925 }, { title: "Clash of the Wolves", year: 1925 }, { title: "The Strong Man", year: 1926 }, { title: "The Black Pirate", year: 1926 }, { title: "Ella Cinders", year: 1926 }, { title: "Beau Geste", year: 1926 }, { title: "The Son of the Sheik", year: 1926 }, { title: "For Heaven's Sake", year: 1926 } ]
操作では、year の値は昇順でソートされますが、year の値が重複しているドキュメントの順序は同じではありません。例、1925 と 1926 の重複値。
一貫性のあるソートを実現するには、一意の値のみを含むフィールドをソートに追加します。次のコマンドは、year フィールドと_id フィールド の両方でソートします。
db.movies.aggregate( [ { $match: { year: { $in: [ 1925, 1926 ] } } }, { $sort: { year: 1, _id: 1 } } ] )
_idフィールドには常に一意の値が含まれ、ソート順序は複数回ソート実行しても一貫しています。
配列フィールドによるソート
MongoDB が配列値フィールドでドキュメントをソートする場合、ソートキーは昇順か降順かのどちらかによって異なります。
昇順ソートでは、ソートキーは配列内の最小値になります。
降順ソートでは、ソートキーは配列内の最も高い値になります。
クエリフィルターは、ソート キーの選択に影響しません。
例、sample_mflixサンプルデータセットの moviesコレクションの次のドキュメントを考えてみましょう。
{ _id: ObjectId("573a1395f29313caabce166c"), title: "The Comancheros", genres: [ "Action", "Western", "Adventure" ] } { _id: ObjectId("573a1391f29313caabcd8521"), title: "The Son of the Sheik", genres: [ "Adventure", "Drama" ] }
次のクエリは、ドキュメントをgenresフィールドで昇順と降順でソートします。
// Ascending sort db.movies.aggregate( [ { $match: { title: { $in: [ "The Comancheros", "The Son of the Sheik" ] } } }, { $sort: { genres: 1 } } ] )
// Descending sort db.movies.aggregate( [ { $match: { title: { $in: [ "The Comancheros", "The Son of the Sheik" ] } } }, { $sort: { genres: -1 } } ] )
上記のクエリではどちらも最初に The Comancheros を返します。これは、Action と Western がそれぞれ genres 配列の最小エントリと最大エントリであるためです。
配列フィールドでフィルタリングおよびソートを行う
配列を含むフィールドでフィルターを適用してソートする場合、フィルターはソートキーとして使用される値に影響を与えません。ソートは常に、配列内のすべての値を潜在的なソートキーとして考慮します。
例、次のクエリは、genres 配列に "Drama" または "Western" が含まれる映画を検索し、その結果を genres で昇順にソートします。
db.movies.aggregate( [ { $match: { title: { $in: [ "The Comancheros", "The Son of the Sheik" ] }, genres: { $in: [ "Drama", "Western" ] } } }, { $sort: { genres: 1 } } ] )
ソートは昇順です。ソートキーは、アルファベット順にソートされた場合、genres 配列の最初の値です。
The Comancherosでは、最初のgenres要素はActionです。この値は、フィルター{ genres: { $in: [ "Drama", "Western" ] } }に一致しないにもかかわらず、ソートキーとして使用されます。The Son of the Sheikでは、最初のgenres要素はAdventureです。同様に、この操作ではフィルターに一致しない場合でも、Adventureをソートキーとして使用します。
クエリは最初に The Comancheros を返します。
Tip
一致した値のみでソート
一致した値のみを潜在的なソートキーとして考慮するには、一致した値を含む新しいフィールドを生成し、そのフィールドでソートします。詳細については、これらのパイプラインステージと式を参照してください。
$sort 演算子とメモリ
$sort と $limit メモリの最適化
が$sort $limitに先行し、途中にドキュメント数を変更するステージがない場合、オプティマイザは$limit を$sort に統合することができます。これにより、$sort 操作の進行中に上位n 6} の結果のみが保持できます。ここでは、n は指定された制限であり、 MongoDB はメモリにn 個の項目のみを保存するだけで済むようになります。この最適化は、allowDiskUse がtrue で、かつn 項目が集計メモリの制限 を超えている場合でも、引き続き適用されます。
最適化はリリースに応じて変更される場合があります。
$sort とメモリ制限
実行に 100 MB を超えるメモリを必要とするパイプライン ステージは、デフォルトで一時ファイルをディスクに書き込みます。これらの一時ファイルはパイプラインの実行中ずっと残り、インスタンスのストレージ容量に影響を与える可能性があります。
個々の find と aggregate コマンドは、次のいずれかの方法で allowDiskUseByDefault パラメーターを上書きできます。
allowDiskUseByDefaultがfalseに設定されている場合に{ allowDiskUse: true }を使用して一時ファイルをディスクに書き込むことを許可するallowDiskUseByDefaultがtrueに設定されている場合に{ allowDiskUse: false }を使用して一時ファイルがディスクに書き込むことを禁止する
注意
MongoDB Atlas でストレージが長時間実行クエリにより一時ファイルで満杯にするのを防ぐために、ストレージのオートスケーリングを構成することを推奨します。
Atlas クラスターでストレージのオートスケーリングが使用されている場合、一時ファイルによってクラスターが 1 つ上のストレージ階層にスケーリングされる場合があります。
詳しくは、「集計パイプラインの制限」を参照してください。
$sort インデックスの使用
$sort演算子は、パイプラインの最初のステージである場合、または$match ステージのみが前にある場合にインデックスを使用できます。
$sortシャーディングされたクラスターで を使用すると、各シャードはインデックスを使用して結果ドキュメントをソートします(使用可能な場合)。次に、 またはシャードの 1 つがストリーム マージソートを実行します。mongos
例
このページの例では、sample_mflixサンプルデータセットのデータを使用します。このデータセットを自己管理型MongoDB配置にロードする方法の詳細については、サンプルデータセットをロードする を参照してください。サンプルデータベースに変更を加えた場合、このページの例を実行するには、データベースを削除して再作成する必要がある場合があります。
昇順および降順ソート
各並べ替えフィールドについて、昇順の場合は 1、降順の場合は -1 に値を設定します。 (例: )。
db.movies.aggregate( [ { $sort: { year: -1, title: 1 } }, { $limit: 5 } ] )
この操作は、moviesコレクション内のドキュメントを year の降順でソートし、次に title の昇順でソートし、最初の 5 つの結果を返します。
ソート操作で異なる BSON types の値を比較する場合、MongoDB は最小値から最大値の順に次の比較順序を使用します。
MinKey(内部型)
null
数値(ints、longs、doubles、decimals)
シンボル、文字列
オブジェクト
配列
BinData
ObjectId
ブール値
日付
タイムスタンプ
正規表現
JavaScriptコード
JavaScript コード(スコープ付き)
MaxKey(内部型)
特定のタイプの比較およびソート順序の詳細については、「比較およびソート順序」を参照してください。
Text Score Metadata Sort
注意
$text は、自己管理型(Atlas 以外)配置に対するテキスト クエリ機能を提供します。MongoDBでホストされているデータに対して、 MongoDB は改良された全文クエリ ソリューションであるMongoDB Search も提供します。
次の例では、sample_mflixサンプルデータセットの moviesコレクションを使用します。これを実行中前に、plotフィールドに テキストインデックスを作成します。
db.movies.createIndex( { plot: "text" } )
$text を含むパイプラインでは、{ $meta: "textScore" } 式を使用して関連性スコアを降順に並べ替えることができます。{ <sort-key> } ドキュメントで、{ $meta: "textScore" } 式を無作為のフィールド名に設定します。フィールド名はクエリ システムによって無視されます。以下に例を挙げます。
db.movies.aggregate( [ { $match: { $text: { $search: "pirate" } } }, { $sort: { score: { $meta: "textScore" }, year: -1 } }, { $limit: 5 } ] )
この操作は$text を持つドキュメントに一致し、次に"textScore" メタデータとyear によって降順にソートされ、最初の 5 つの結果が返されます。ソートドキュメント内のscore フィールド名はクエリ システムによって無視されます。プロジェクションには"textScore" メタデータは含まれず、一致するドキュメントの一部としてメタデータは返されません。詳しくは、$meta を参照してください。
このページのC#の例では、Atlasサンプルデータセット の sample_mflixデータベースを使用します。MongoDB Atlasクラスターを無料で作成して、サンプルデータセットをロードする方法については、 MongoDB .NET/ C#ドライバーのドキュメントの「 開始 」を参照してください。
次の Movie クラスは、sample_mflix.movies コレクション内のドキュメントをモデル化します。
[] public class Movie { [] public ObjectId Id { get; set; } [] public string Title { get; set; } = null!; [] public int? Year { get; set; } [] public int? Runtime { get; set; } [] public string? Rated { get; set; } [] public int Metacritic { get; set; } [] public string? Plot { get; set; } [] public string? Type { get; set; } [] public string[]? Cast { get; set; } [] public string[]? Directors { get; set; } [] public string[]? Writers { get; set; } [] public ImdbData? Imdb { get; set; } }
MongoDB .NET/ C#ドライバーを使用して$sort ステージを集計パイプラインに追加するには、 PipelineDefinitionオブジェクトで UnionWith() メソッドを呼び出します。
次の例では、まず Metacritic が 100 に等しい Movie ドキュメントをフィルターし、次に Year フィールドで結果を降順に、Title フィールドで昇順にソートするパイプライン ステージを作成します。
var pipeline = new EmptyPipelineDefinition<Movie>() .Match(Builders<Movie>.Filter.Eq(m => m.Metacritic, 100)) .Sort(Builders<Movie>.Sort.Combine( Builders<Movie>.Sort.Descending(m => m.Year), Builders<Movie>.Sort.Ascending(m => m.Title)));
MongoDB Node.jsドライバーを使用して $sort ステージを集計パイプラインに追加するには、パイプラインオブジェクトで $sort 演算子を使用します。
次の例では、入力された movie ドキュメントを最初に year フィールドで降順にソートし、その後 title フィールドで昇順にソートするパイプラインステージを作成します。次に、この例は集計パイプラインを実行します。
const pipeline = [{ $sort: { year: -1, title: 1 } }]; const cursor = collection.aggregate(pipeline); return cursor;
詳細
を使用する完全な集計の例については、「$sort 完全な集計パイプライン チュートリアル 」を参照してください。