cursor.sort()
定義
cursor.sort(sort)
重要
mongosh メソッド
このページでは、
mongosh
メソッドが文書化されます。これは Node.js などの言語固有のドライバーのドキュメントではありません。MongoDB API ドライバーについては、各言語の MongoDB ドライバー ドキュメントを参照してください。
クエリが一致するドキュメントを返す順序を指定します。データベースからドキュメントを取得する前に、カーソルに
sort()
を適用する必要があります。
互換性
次の環境でホストされる配置には cursor.sort(sort)
を使用できます。
MongoDB Atlas はクラウドでの MongoDB 配置のためのフルマネージド サービスです
MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン
MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン
構文
sort()
メソッドには次のパラメーターがあります。
Parameter | タイプ | 説明 |
---|---|---|
sort | ドキュメント | 結果セットのソート順を定義するドキュメント。 |
sort
パラメーターには、フィールドと値のペアが次の形式で含まれます。
{ field: value }
ソート ドキュメントでは、既存のフィールドで昇順または降順のソートを指定したり、テキスト スコア メタデータでソートしたりできます。
動作
制限
最大 32 個のキーでソートすることができます。
重複するフィールドを含むソート パターンを指定すると、エラーが発生します。
ソートの一貫性
MongoDB では、コレクション内のドキュメントを特定の順序で保存することはありません。重複する値を含むフィールドでソートする場合、それらの値を含むドキュメントは任意の順序で返されます。
一貫したソート順序が必要な場合は、一意の値を含むフィールドを少なくとも 1 つ含めてソートしてください。これを保証する最も簡単な方法は、_id
フィールドをソートのクエリに含めることです。
次の restaurant
コレクションについて考えてみます。
db.restaurants.insertMany( [ { "_id" : 1, "name" : "Central Park Cafe", "borough" : "Manhattan"}, { "_id" : 2, "name" : "Rock A Feller Bar and Grill", "borough" : "Queens"}, { "_id" : 3, "name" : "Empire State Pub", "borough" : "Brooklyn"}, { "_id" : 4, "name" : "Stan's Pizzaria", "borough" : "Manhattan"}, { "_id" : 5, "name" : "Jane's Deli", "borough" : "Brooklyn"}, ] );
次のコマンドは、sort()
メソッドを使用して borough
フィールドでソートします。
db.restaurants.find().sort( { "borough": 1 } )
この例では、borough
フィールドに Manhattan
と Brooklyn
の両方で重複する値が含まれているため、ソート順序に一貫性がない可能性があります。ドキュメントは borough
のアルファベット順に返されますが、borough
の値が重複しているドキュメントでは、同じソートを複数回実行すると順序が異なる場合があります。たとえば、上記のコマンドを 2 回実行した結果を次に示します。
{ "_id" : 3, "name" : "Empire State Pub", "borough" : "Brooklyn" } { "_id" : 5, "name" : "Jane's Deli", "borough" : "Brooklyn" } { "_id" : 1, "name" : "Central Park Cafe", "borough" : "Manhattan" } { "_id" : 4, "name" : "Stan's Pizzaria", "borough" : "Manhattan" } { "_id" : 2, "name" : "Rock A Feller Bar and Grill", "borough" : "Queens" } { "_id" : 5, "name" : "Jane's Deli", "borough" : "Brooklyn" } { "_id" : 3, "name" : "Empire State Pub", "borough" : "Brooklyn" } { "_id" : 4, "name" : "Stan's Pizzaria", "borough" : "Manhattan" } { "_id" : 1, "name" : "Central Park Cafe", "borough" : "Manhattan" } { "_id" : 2, "name" : "Rock A Feller Bar and Grill", "borough" : "Queens" }
borough
の値はまだアルファベット順にソートされていますが、borough
の値が重複しているドキュメントの順序(Manhattan
と Brooklyn
)は同じではありません。
一貫性のあるソートを実現するには、ユニークな値のみを含むフィールドをソートに追加します。次のコマンドは、sort()
メソッドを使用して、borough
フィールドと _id
フィールドの両方でソートします。
db.restaurants.find().sort( { "borough": 1, "_id": 1 } )
_id
フィールドには常に一意の値のみが含まれることが保証されているため、同じソートを複数回実行しても返されるソート順序は常に同じになります。
昇順および降順ソート
昇順または降順のソートを指定するには、ソート パラメーターで、ソートするフィールドを 1 つまたは複数指定し、1
または -1
の値を指定します。
次の操作では、ドキュメントを最初に age
フィールドで降順にソートし、次に posts
フィールドで昇順にソートします。
db.users.find({ }).sort( { age : -1, posts: 1 } )
ソート操作で異なる BSON types の値を比較する場合、MongoDB は最小値から最大値の順に次の比較順序を使用します。
MinKey(内部型)
null
数値(ints、longs、doubles、decimals)
シンボル、文字列
オブジェクト
配列
BinData
ObjectId
ブール値
日付
タイムスタンプ
正規表現
MaxKey(内部型)
特定のタイプの比較およびソート順序の詳細については、「比較およびソート順序」を参照してください。
Text Score Metadata Sort
注意
$text
は、自己管理型(Atlas 以外)配置に対するテキスト クエリ機能を提供します。MongoDB Atlas でホストされているデータに対して、MongoDB は改良された全文クエリ ソリューションである Atlas Search を提供します。
$text
を使用する場合は、 { $meta: "textScore" }
式を使用して関連性スコアを降順に並べ替えることができます。
次のサンプル ドキュメントでは、 "textScore"
メタデータによる降順のソートを指定しています。
db.users.find( { $text: { $search: "operating" } }, { score: { $meta: "textScore" }} ).sort({ score: { $meta: "textScore" } })
"textScore"
メタデータは降順でソートされます。
詳細については、$meta
を参照してください。
配列フィールドによるソート
MongoDB が配列値フィールドでドキュメントをソートする場合、ソートキーは昇順か降順かのどちらかによって異なります。
昇順ソートでは、ソートキーは配列内の最小値になります。
降順ソートでは、ソートキーは配列内の最も高い値になります。
クエリフィルターは、ソート キーの選択に影響しません。
たとえば、次のドキュメントを使用してshoes
コレクションを作成します。
db.shoes.insertMany( [ { _id: 'A', sizes: [ 7, 11 ] }, { _id: 'B', sizes: [ 8, 9, 10 ] } ] )
次のクエリは、ドキュメントをsizes
フィールドで昇順と降順でソートします。
// Ascending sort db.shoes.find().sort( { sizes: 1 } ) // Descending sort db.shoes.find().sort( { sizes: -1 } )
上記のクエリではどちらのクエリでも、最初に_id: 'A'
を持つドキュメントが返されます。これは、 7
と11
のサイズがそれぞれ、 sizes
配列のエントリの最小値と最大値であるためです。
次のクエリは、 10より大きいサイズの鍵を検索し、結果を鍵サイズの昇順でソートします。
db.shoes.find( { sizes: { $gte: 7 } } ).sort( { sizes: 1 } )
このクエリは、フィルターに7
sizes
の条件が含まれているにもかかわらず、最初に_id: 'A'
を持つドキュメントを返します。クエリフィルターはソートキーの選択に影響しないためです。
ソートとインデックスの使用
MongoDB は、ソート フィールドを含むインデックスからソート操作の結果を取得できます。MongoDB では、ソートでクエリ述語と同じインデックスを使用する場合 、ソート操作をサポートするために複数のインデックスを使用する場合があります。
MongoDB では、1 つまたは複数のインデックスを使用してソート順序を取得できない場合、データに対してブロッキングソート操作を実行する必要があります。ブロッキングソートは、結果を返す前に MongoDB が、ソートへのすべての入力ドキュメントを消費して処理する必要があることを示します。ブロッキングソートは、コレクションまたはデータベースに対する同時操作をブロックしません。
インデックスを使用するソート操作は、多くの場合、ブロッキングソートよりもパフォーマンスが優れています。ソート操作をサポートするインデックスの作成の詳細については、「クエリ結果をソートするためにインデックスを使用する」を参照してください。
MongoDB でのブロッキング ソート操作に 100 メガバイトを超えるシステム メモリが必要な場合、クエリが cursor.allowDiskUse()
を指定していない限り、MongoDB はエラーを返します。allowDiskUse()
を指定することで、MongoDB は 100 メガバイトのシステムメモリ制限を超えるデータをディスク上の一時ファイルに保存し、ブロッキングソート操作を処理することができます。
MongoDB がブロッキングソートを実行する必要があるかどうかを確認するには、クエリにcursor.explain()
を追加し、explain の結果を確認します。クエリプランに SORT
ステージが含まれている場合、MongoDB は 100 MB のメモリ制限に従ってブロッキングソート操作を実行する必要があります。
ブロッキングソートがメモリを消費しすぎるのを防ぐ方法は次のとおりです。
ソート操作をサポートするインデックスを作成します。詳細と例については、「インデックスを使用してクエリ結果をソートする」を参照してください。
cursor.limit()
とcursor.sort()
を組み合わせて使用することで、ソートするデータの量を制限します。詳細と例については、「結果の制限」を参照してください。
結果を制限する
sort()
を limit()
と組み合わせて使用すると、(ソート順序で)最初の k
個のドキュメントを返すことができます。ここで示した k
は指定された制限です。
MongoDB では、ソート順序をインデックススキャンで取得できない場合、Top-k ソートアルゴリズムを使用します。このアルゴリズムでは、基礎となるインデックスやコレクションへのアクセスによってそれまでに確認された結果のうち、最初の(ソート順序によっては最後の) k
件をバッファします。このk
件の結果のメモリフットプリントがいずれかの時点で100メガバイトを超えると、クエリでcursor.allowDiskUse()
が指定されていない限り、クエリは失敗します。
プロジェクションとの相互作用
結果セットがソートされ、かつプロジェクションされる場合、MongoDB クエリ エンジンは常に最初にソートを適用します。
例
コレクション orders
には次のドキュメントが含まれています:
{ _id: 1, item: { category: "cake", type: "chiffon" }, amount: 10 } { _id: 2, item: { category: "cookies", type: "chocolate chip" }, amount: 50 } { _id: 3, item: { category: "cookies", type: "chocolate chip" }, amount: 15 } { _id: 4, item: { category: "cake", type: "lemon" }, amount: 30 } { _id: 5, item: { category: "cake", type: "carrot" }, amount: 20 } { _id: 6, item: { category: "brownies", type: "blondie" }, amount: 10 }
次のクエリは orders
コレクションからすべてのドキュメントを返しますが、ソート順を指定していません。
db.orders.find()
このクエリでは、返すドキュメントの順序は次のように一定ではありません。
{ "_id" : 1, "item" : { "category" : "cake", "type" : "chiffon" }, "amount" : 10 } { "_id" : 2, "item" : { "category" : "cookies", "type" : "chocolate chip" }, "amount" : 50 } { "_id" : 3, "item" : { "category" : "cookies", "type" : "chocolate chip" }, "amount" : 15 } { "_id" : 4, "item" : { "category" : "cake", "type" : "lemon" }, "amount" : 30 } { "_id" : 5, "item" : { "category" : "cake", "type" : "carrot" }, "amount" : 20 } { "_id" : 6, "item" : { "category" : "brownies", "type" : "blondie" }, "amount" : 10 }
次のクエリは、 amount
フィールドで降順にソートすることを指定します。
db.orders.find().sort( { amount: -1 } )
クエリは、amount
の降順で次のドキュメントを返します。
{ "_id" : 2, "item" : { "category" : "cookies", "type" : "chocolate chip" }, "amount" : 50 } { "_id" : 4, "item" : { "category" : "cake", "type" : "lemon" }, "amount" : 30 } { "_id" : 5, "item" : { "category" : "cake", "type" : "carrot" }, "amount" : 20 } { "_id" : 3, "item" : { "category" : "cookies", "type" : "chocolate chip" }, "amount" : 15 } { "_id" : 1, "item" : { "category" : "cake", "type" : "chiffon" }, "amount" : 10 } { "_id" : 6, "item" : { "category" : "brownies", "type" : "blondie" }, "amount" : 10 }
次のクエリは、埋め込みドキュメント item
のフィールドを使用してソート順序を指定します。このクエリは、最初に category
フィールドを昇順でソートし、次に各 category
内で type
フィールドで昇順にソートします。
db.orders.find().sort( { "item.category": 1, "item.type": 1 } )
このクエリでは、次のドキュメントを最初に category
フィールドでソートし、各カテゴリ内では type
フィールドの順にソートして返します。
{ "_id" : 6, "item" : { "category" : "brownies", "type" : "blondie" }, "amount" : 10 } { "_id" : 5, "item" : { "category" : "cake", "type" : "carrot" }, "amount" : 20 } { "_id" : 1, "item" : { "category" : "cake", "type" : "chiffon" }, "amount" : 10 } { "_id" : 4, "item" : { "category" : "cake", "type" : "lemon" }, "amount" : 30 } { "_id" : 2, "item" : { "category" : "cookies", "type" : "chocolate chip" }, "amount" : 50 } { "_id" : 3, "item" : { "category" : "cookies", "type" : "chocolate chip" }, "amount" : 15 }
自然な順序で返す
$natural
パラメーターを使うと、データベース内の自然な順序に従って項目を返します。この順序付けは内部実装機能であり、ドキュメントが特定の順序になることを前提にしないでください。
インデックスの使用
$natural
によるソートを含むクエリでは、次の例外を除き、クエリ述語を実行するためにインデックスは使用されません。クエリ述語が_id
フィールド { _id: <value> }
の等価条件である場合のみ、$natural
によるソートを含むクエリで _id
インデックスを使用できます。