MongoDB聚合运算符:$top
文章目录
- [MongoDB聚合运算符:top](#MongoDB聚合运算符:top)
$top
聚合运算符返回一个指定顺序分组的第一个元素。
语法
js
{
$top:
{
sortBy: { <field1>: <sort order>, <field2>: <sort order> ... },
output: <expression>
}
}
字段说明:
字段 | 是否必须 | 描述 |
---|---|---|
sortBy | 是 | 指定结果排序方式,跟$sort 一样 |
output | 是 | 指定分组元素输出的内容,可以是任何合法的表达式 |
用法
$top
不支持作为聚合表达式。$top
只支持作为window 操作符
。- 聚合管道调用
$top
受100M的限制,如果单组超过这一限制将报错。
关于null和缺失值的处理
$top
不会过滤掉空值,也就是空值也参与排序$top
会将缺失值转换为null,也就是缺失值会当做null排序
下面的聚合返回分组中得分最高的文档:
js
db.aggregate( [
{
$documents: [
{ playerId: "PlayerA", gameId: "G1", score: 1 },
{ playerId: "PlayerB", gameId: "G1", score: 2 },
{ playerId: "PlayerC", gameId: "G1", score: 3 },
{ playerId: "PlayerD", gameId: "G1"},
{ playerId: "PlayerE", gameId: "G1", score: null }
]
},
{
$group:
{
_id: "$gameId",
playerId:
{
$top:
{
output: [ "$playerId", "$score" ],
sortBy: { "score": -1 }
}
}
}
}
] )
在这个例子中:
- 使用
$documents
阶段创建了一些字面量(常量)文档,包含了选手的得分 $group
阶段根据gameId
对文档进行了分组,显然文档中的gameId
都是G1
PlayerD
的得分缺失,PlayerE
的得分为null
,他们的得分都会被当做null
处理playerId
字段和score
字段被指定为输出:["$playerId"," $score"]
,以数组的形式返回- 指定了排序的方式,按照
score
逆序:sortBy: { "score": -1 }
PlayerD
和PlayerE
并列为第一的元素,PlayerD
作为第一个score
返回- 要解决因为多个元素空值导致的问题,就需要添加更多的字段参与到排序
js
[
{
_id: 'G1',
playerId: [ [ 'PlayerD', null ] ]
}
]
举例
使用下面的命令,创建gamescores
集合:
js
db.gamescores.insertMany([
{ playerId: "PlayerA", gameId: "G1", score: 31 },
{ playerId: "PlayerB", gameId: "G1", score: 33 },
{ playerId: "PlayerC", gameId: "G1", score: 99 },
{ playerId: "PlayerD", gameId: "G1", score: 1 },
{ playerId: "PlayerA", gameId: "G2", score: 10 },
{ playerId: "PlayerB", gameId: "G2", score: 14 },
{ playerId: "PlayerC", gameId: "G2", score: 66 },
{ playerId: "PlayerD", gameId: "G2", score: 80 }
])
查找单个游戏的第一名
使用$top
查找单场比赛的第一名:
js
db.gamescores.aggregate( [
{
$match : { gameId : "G1" }
},
{
$group:
{
_id: "$gameId",
playerId:
{
$top:
{
output: [ "$playerId", "$score" ],
sortBy: { "score": -1 }
}
}
}
}
] )
在本例的管道中:
- 使用
$match
阶段用一个gameId
对结果进行筛选,即:G1
- 使用
$group
阶段依据gameId
对结果进行分组,本例中只有一个分组G1
- 使用
output : ["$playerId"," $score"]
为top
指定输出字段 - 使用
sortBy: { "score": -1 }
按照得分进行逆序排序 - 使用
$top
返回游戏得分最高的元素
操作返回下面的结果:
js
[ { _id: 'G1', playerId: [ 'PlayerC', 99 ] } ]
查所有游戏的第一名
使用$top
查找所有游戏的第一名:
js
db.gamescores.aggregate( [
{
$group:
{ _id: "$gameId", playerId:
{
$top:
{
output: [ "$playerId", "$score" ],
sortBy: { "score": -1 }
}
}
}
}
] )
在本例的管道中:
- 使用
$group
按照groupId
对结果排序 - 使用
$top
返回所有游戏中得分最低的 - 使用
output : ["$playerId", "$score"]
指定top
输出的字段 - 使用
sortBy: { "score": -1 }
按照得分进行逆序排序
操作返回下面的结果:
js
[
{ _id: 'G2', playerId: [ 'PlayerD', 80 ] },
{ _id: 'G1', playerId: [ 'PlayerC', 99 ] }
]