Docs 菜单
Docs 主页
/
MongoDB Manual
/ / /

复合索引排序顺序

在此页面上

  • 用例(Use Case)
  • 例子
  • 排行榜的支持索引
  • 反向结果
  • 不支持的查询
  • 了解详情

索引会按升序 ( 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, } )

后退

创建