定義
互換性
次の環境でホストされる配置には $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 sortdb.movies.aggregate( [ { $match: { title: { $in: [ "The Comancheros", "The Son of the Sheik" ] } } }, { $sort: { genres: 1 } }] )// Descending sortdb.movies.aggregate( [ { $match: { title: { $in: [ "The Comancheros", "The Son of the Sheik" ] } } }, { $sort: { genres: -1 } }] )上記のクエリはどちらも、Action と Western がそれぞれの genres 配列の最小値と最大値であるため、The Comancheros を最初に返します。
配列フィールドでフィルタリングおよびソートを行う
配列を含むフィールドでフィルターを適用してソートする場合、フィルターはソートキーとして使用される値に影響を与えません。ソートは常に、配列内のすべての値を潜在的なソートキーとして考慮します。
例として、次のクエリは、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結果のみが保持できます。ここでは、 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 を使用すると、各シャードは利用可能なインデックスを使用して結果のドキュメントをソートします。次に、 mongos またはシャードの 1 つがストリーム マージソートを実行します。
例
このページの例では、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 コレクション内のドキュメントをモデル化します。
[BsonIgnoreExtraElements]public class Movie{ [BsonId] public ObjectId Id { get; set; } [BsonElement("title")] public string Title { get; set; } = null!; [BsonElement("year")] public int? Year { get; set; } [BsonElement("runtime")] public int? Runtime { get; set; } [BsonElement("rated")] public string? Rated { get; set; } [BsonElement("metacritic")] public int Metacritic { get; set; } [BsonElement("plot")] public string? Plot { get; set; } [BsonElement("type")] public string? Type { get; set; } [BsonElement("cast")] public string[]? Cast { get; set; } [BsonElement("directors")] public string[]? Directors { get; set; } [BsonElement("writers")] public string[]? Writers { get; set; } [BsonElement("imdb")] 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 を使用する完全な集計の例については、完全な集計パイプラインチュートリアルをご覧ください。