复合索引排序顺序
索引存储字段引用,顺序为升序(1)或降序(-1)。对于复合索引,排序顺序可以确定索引是否支持排序操作。
复合索引支持与索引排序顺序或索引逆排序顺序匹配的排序操作。
用例
一个手机游戏有一个排行榜,显示以下信息
最高游戏分数
达到每个分数的用户
每个分数的达成日期
应用程序首先按 分数 降序排序排行榜。然后,与每个 分数 关联的 用户名 按升序(字母顺序)排序。
如果索引中的排序顺序与查询中的排序顺序匹配,则复合索引可以提高排行榜的性能。
示例
考虑一个包含以下文档的 排行榜 集合
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()。