$maxN(聚合累加器)
定义
语法
{ $maxN: { input: <expression>, n: <expression> } }
input指定一个表达式,作为$maxN的输入。它对组内的每个元素进行评估,并保留最大的n个值。n限制每个组的结果数量,n必须是正整数表达式,可以是常量或依赖于$group的_id值。$group.
行为
结果类型
$maxN根据BSON比较顺序比较输入数据,以确定适当的输出类型。当输入数据包含多种数据类型时,$maxN的输出类型是比较顺序中的最高
类型。
$maxN会过滤掉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", maximumThreeScores: { $maxN: { input: "$score", n: 4 } } } } ] )
考虑以下聚合,该聚合从分组中返回最大n个文档
在这个例子中
$documents创建包含玩家得分的文档。$group按gameId对文档进行分组。这个例子只有一个gameId,即G1。PlayerD的得分为缺失值,PlayerE的得分为null。这两个值都被视为null。将
maximumThreeScores字段指定为$maxN,输入为: "$score",并以数组形式返回。
[ { _id: 'G1', maximumThreeScores: [ 3, 2, 1 ] } ]
比较 $maxN 和 $topN 累加器
两者 $maxN 和 $topN 累加器可以完成类似的结果。
一般来说
限制
窗口函数和聚合表达式支持
您可以使用 $maxN 作为累加器。
内存限制考虑
调用 $maxN 的聚合管道受到 100 MB 限制。如果单个组的此限制被超过,聚合将失败并显示错误。
示例
考虑一个包含以下文档的 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 } ])
找到单个游戏中最高三个分数。
您可以使用$maxN累加器来找到单个游戏中的最高三个分数。
db.gamescores.aggregate( [ { $match : { gameId : "G1" } }, { $group: { _id: "$gameId", maxThreeScores: { $maxN: { input: ["$score","$playerId"], n:3 } } } } ] )
示例管道
使用
$match来按单个gameId过滤结果。在这种情况下,G1。使用
$group按gameId对结果进行分组。在这种情况下,G1。使用
input : ["$score","$playerId"]指定输入给$maxN的字段。使用
$maxN返回G1游戏的最高三个分数元素,其中n : 3。
该操作返回以下结果
[ { _id: 'G1', maxThreeScores: [ [ 99, 'PlayerC' ], [ 33, 'PlayerB' ], [ 31, 'PlayerA' ] ] } ]
在多个游戏中找到最高三个分数
您可以使用$maxN累加器来找到每个游戏中的最高n个分数。
db.gamescores.aggregate( [ { $group: { _id: "$gameId", maxScores: { $maxN: { input: ["$score","$playerId"], n: 3 } } } } ] )
示例管道
使用
$group按gameId对结果进行分组。使用
$maxN返回每个游戏的最高三个分数元素,其中n: 3。使用
input: ["$score","$playerId"]指定输入给$maxN的字段。
该操作返回以下结果
[ { _id: 'G1', maxScores: [ [ 99, 'PlayerC' ], [ 33, 'PlayerB' ], [ 31, 'PlayerA' ] ] }, { _id: 'G2', maxScores: [ [ 80, 'PlayerD' ], [ 66, 'PlayerC' ], [ 14, 'PlayerB' ] ] } ]
基于分组键计算 n(对于 $group)
您还可以动态分配 n 的值。在这个例子中,使用了 $cond 表达式在 gameId 字段上。
db.gamescores.aggregate([ { $group: { _id: {"gameId": "$gameId"}, gamescores: { $maxN: { input: ["$score","$playerId"], n: { $cond: { if: {$eq: ["$gameId","G2"] }, then: 1, else: 3 } } } } } } ] )
示例管道
使用
$group按gameId对结果进行分组。使用
input : ["$score","$playerId"]指定$maxN的输入字段。如果
gameId是G2,则n为 1,否则n为 3。
该操作返回以下结果
[ { _id: { gameId: 'G2' }, gamescores: [ [ 80, 'PlayerD' ] ] }, { _id: { gameId: 'G1' }, gamescores: [ [ 99, 'PlayerC' ], [ 33, 'PlayerB' ], [ 31, 'PlayerA' ] ] } ]