广州白云区最新信息,网站布局优化怎么做,企业网站整站,大连网站建设哪家公司好MongoDB聚合运算符#xff1a;$topN 文章目录 MongoDB聚合运算符#xff1a;$topN语法用法关于null和缺失值的处理BSON数据类型排序 举例查找三个得分最高的查找全部游戏中三个最高的得分基于分组key来计算参数n $topN聚合运算符返回分组中指定顺序的最前面
n个元素#xf…MongoDB聚合运算符$topN 文章目录 MongoDB聚合运算符$topN语法用法关于null和缺失值的处理BSON数据类型排序 举例查找三个得分最高的查找全部游戏中三个最高的得分基于分组key来计算参数n $topN聚合运算符返回分组中指定顺序的最前面
n个元素如果分组中的元素数量小于
n则返回分组的全部元素。从MongoDB5.2开始支持。 语法
{$topN:{n: expression,sortBy: { field1: sort order, field2: sort order ... },output: expression}
}n用于限制每组结果的数量必须是正整数表达式要么是常数要么取决于$group的_id 值sortBy制定返回结果的顺序语法类似于$sortoutput指定分组元素输出的内容可以是任何合法的表达式。
用法
$topN不支持作为聚合表达式。$topN只支持作为window 操作符。聚合管道调用$topN受100M的限制如果单组超过这一限制将报错。
关于null和缺失值的处理
$topN不会过滤掉空值$topN会将缺失值转换为null
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:{$topN:{output: [ $playerId, $score ],sortBy: { score: 1 },n: 3}}}}
] )在这个例子中
使用$documents阶段创建了一些字面量常量文档包含了选手的得分$group阶段根据gameId对文档进行了分组显然文档中的gameId都是G1PlayerD的得分缺失PlayerE的得分为null他们的得分都会被当做null处理playerId字段和score字段被指定为输出[$playerId, $score]以数组的形式返回sortBy: { score: 1 }指定了排序的方式空值被排在最前面返回playerId数组
如下
[{_id: G1,playerId: [ [ PlayerD, null ], [ PlayerE, null ], [ PlayerA, 1 ] ]}
]BSON数据类型排序
当不同类型排序是使用BSON数据类型的顺序进行排序
当进行正序排序时由小到大字符串的优先级在数值之前当进行逆序排序时由大到小字符串的优先级在数值之前
下面的例子中包含了字符串和数值类型
db.aggregate( [{$documents: [{ playerId: PlayerA, gameId: G1, score: 1 },{ playerId: PlayerB, gameId: G1, score: 2 },{ playerId: PlayerC, gameId: G1, score: }]},{$group:{_id: $gameId,playerId: {$topN:{output: [$playerId,$score],sortBy: {score: -1},n: 3}}}}
] )在这个例子中
PlayerA的得分是整数1PlayerB的得分是字符串2PlayerC的得分是空字符串
因为排序指定为逆序{ score : -1 }字符串的字面量排在PlayerA的数值得分之前
[{_id: G1,playerId: [ [ PlayerB, 2 ], [ PlayerC, ], [ PlayerA, 1 ] ]}
]举例
使用下面的命令创建gamescores集合
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 }
])查找三个得分最高的
使用$topN查找单个游戏中得分最高的3个
db.gamescores.aggregate( [{$match : { gameId : G1 }},{$group:{_id: $gameId,playerId:{$topN:{output: [$playerId, $score],sortBy: { score: -1 },n:3}}}}
] )本例中
使用$match阶段用一个gameId对结果进行筛选即G1使用$group阶段依据gameId对结果进行分组本例中只有一个分组G1使用sortBy: { score: -1 }按照得分进行逆序排序使用output : [$playerId, $score]为$topN指定输出字段使用$topN返回游戏得分最高的3个选手和得分
结果如下
[{_id: G1,playerId: [ [ PlayerC, 99 ], [ PlayerB, 33 ], [ PlayerA, 31 ] ]}
]与下面的SQL查询等价
SELECT T3.GAMEID,T3.PLAYERID,T3.SCORE
FROM GAMESCORES AS GS
JOIN (SELECT TOP 3GAMEID,PLAYERID,SCOREFROM GAMESCORESWHERE GAMEID G1ORDER BY SCORE DESC) AS T3ON GS.GAMEID T3.GAMEID
GROUP BY T3.GAMEID,T3.PLAYERID,T3.SCOREORDER BY T3.SCORE DESC查找全部游戏中三个最高的得分
使用$topN查找所有游戏中得分最高的三个
db.gamescores.aggregate( [{$group:{ _id: $gameId, playerId:{$topN:{output: [ $playerId,$score ],sortBy: { score: -1 },n: 3}}}}
] )在本例中
使用$group按照groupId对结果排序使用output : [$playerId, $score]指定bottom输出的字段使用sortBy: { score: -1 }按照得分进行逆序排序使用$topN返回所有游戏中得分最高的三个
结果如下
[{_id: G1,playerId: [ [ PlayerC, 99 ], [ PlayerB, 33 ], [ PlayerA, 31 ] ]},{_id: G2,playerId: [ [ PlayerD, 80 ], [ PlayerC, 66 ], [ PlayerB, 14 ] ]}
]这个操作与下面的SQL语句等价
SELECT PLAYERID,GAMEID,SCORE
FROM(SELECT ROW_NUMBER() OVER (PARTITION BY GAMEID ORDER BY SCORE DESC) AS GAMERANK,GAMEID,PLAYERID,SCOREFROM GAMESCORES
) AS T
WHERE GAMERANK 3
ORDER BY GAMEID基于分组key来计算参数n
可以动态指定n的值在本例中$cond表达式用在gameId字段
db.gamescores.aggregate([{$group:{_id: {gameId: $gameId},gamescores:{$topN:{output: $score,n: { $cond: { if: {$eq: [$gameId,G2] }, then: 1, else: 3 } },sortBy: { score: -1 }}}}}
] )在本例中
使用$group按照groupId对结果排序使用output : $score指定$topN输出的字段如果gameId是G2则n为1否则n为3使用sortBy: { score: -1 }按照得分进行逆序排序
操作结果如下
[{ _id: { gameId: G1 }, gamescores: [ 99, 33, 31 ] },{ _id: { gameId: G2 }, gamescores: [ 80 ] }
]