複合インデックスのソート順
インデックスにはフィールドへの参照が昇順( 1
)または降順( -1
)のいずれかで保存されます。 複合インデックスの場合、ソート順序によって、インデックスがソート操作をサポートできるかどうかが決まります。
複合インデックスは、インデックスのソート順序、またはインデックスの逆ソート順序のいずれかに一致するソート操作をサポートします。
ユースケース
モバイルゲームには、次の情報を表示するリーダーボードがあります。
最高ゲームスコア
各スコアを実行したユーザー
各スコアが実行された日付
アプリケーションは、リーダーボードを最初にscore
から降順にソートします。 次に、各score
に関連付けられたusername
が昇順(アルファベット順)でソートされます。
複合インデックスを使用すると、インデックスのソート順序がクエリのソート順序と一致する場合、リーダーボードのパフォーマンスを向上させることができます。
例
次のドキュメントを含むleaderboard
コレクションについて考えてみます。
db.leaderboard.insertMany( [ { "score": 50, "username": "Alex Martin", "date": ISODate("2022-03-01T00:00:00Z") }, { "score": 55, "username": "Laura Garcia", "date": ISODate("2022-03-02T00:00:00Z") }, { "score": 60, "username": "Alex Martin", "date": ISODate("2022-03-03T00:00:00Z") }, { "score": 60, "username": "Riya Patel", "date": ISODate("2022-03-04T00:00:00Z") }, { "score": 50, "username": "Laura Garcia", "date": ISODate("2022-03-05T00:00:00Z") } ] )
このクエリは、リーダーボードの結果を返します。
db.leaderboard.find().sort( { score: -1, username: 1 } )
出力:
[ { _id: ObjectId("632235700646eaee87a56a74"), score: 60, username: 'Alex Martin', date: ISODate("2022-03-03T00:00:00.000Z") }, { _id: ObjectId("632235700646eaee87a56a75"), score: 60, username: 'Riya Patel', date: ISODate("2022-03-04T00:00:00.000Z") }, { _id: ObjectId("632235700646eaee87a56a73"), score: 55, username: 'Laura Garcia', date: ISODate("2022-03-02T00:00:00.000Z") }, { _id: ObjectId("632235700646eaee87a56a72"), score: 50, username: 'Alex Martin', date: ISODate("2022-03-01T00:00:00.000Z") }, { _id: ObjectId("632235700646eaee87a56a76"), score: 50, username: 'Laura Garcia', date: ISODate("2022-03-05T00:00:00.000Z") } ]
結果は、最初にスコアの降順でソートされ、次にユーザー名で昇順(アルファベット順)でソートされます。
リーダーボードのサポート インデックス
次のインデックスを使用すると、インデックスのソート順がクエリで使用されるソート順と一致するため、リーダーボード結果のパフォーマンスが向上します。
db.leaderboard.createIndex( { score: -1, username: 1 } )
この複合インデックスは以下を保存します。
score
値を降順で並べ替えます。username
昇順(アルファベット順)の値。
結果を元に戻す
MongoDB はどちらの方向にも複合インデックスをトラバースできます。 アプリケーションでユーザーがリーダーボードを逆の順序で表示できる場合、インデックスはそのクエリもサポートします。
次のクエリは、リーダーボードを逆の順序で返します。結果は最初にscore
値の昇順でソートされ、次にusername
値の降順でソートされます(アルファベット順に逆)。
db.leaderboard.find().sort( { score: 1, username: -1 } )
出力:
[ { _id: ObjectId("632235700646eaee87a56a76"), score: 50, username: 'Laura Garcia', date: ISODate("2022-03-05T00:00:00.000Z") }, { _id: ObjectId("632235700646eaee87a56a72"), score: 50, username: 'Alex Martin', date: ISODate("2022-03-01T00:00:00.000Z") }, { _id: ObjectId("632235700646eaee87a56a73"), score: 55, username: 'Laura Garcia', date: ISODate("2022-03-02T00:00:00.000Z") }, { _id: ObjectId("632235700646eaee87a56a75"), score: 60, username: 'Riya Patel', date: ISODate("2022-03-04T00:00:00.000Z") }, { _id: ObjectId("632235700646eaee87a56a74"), score: 60, username: 'Alex Martin', date: ISODate("2022-03-03T00:00:00.000Z") } ]
このクエリは{ score: -1, username: 1 }
インデックスでサポートされています。
サポートされていないクエリ
複合インデックスは、ソート順序がインデックスと一致しない、またはインデックスの逆のクエリをサポートできません。 そのため、 { score:
-1, username: 1 }
インデックスでは、次のクエリのように、 score
値の昇順でソートし、次にusername
値の昇順でソートすることはできません。
db.leaderboard.find().sort( { score: 1, username: 1 } )
さらに、ソート操作でインデックスを使用するには、ソートで指定されたフィールドがインデックスに表示されるのと 同じ順序 で表示される必要があります。 そのため、上記のインデックスはこのクエリをサポートできません。
db.leaderboard.find().sort( { username: 1, score: -1, } )
詳細
ソート順序とインデックスの詳細については、「クエリ結果をソートするためにインデックスを使用する 」を参照してください。
クエリ結果の並べ替えの詳細については、
sort()
を参照してください。