$maxN(聚合累加器)
定义
语法
{ $maxN: { input: <expression>, n: <expression> } }
input
指定一个表达式,作为$maxN
的输入。 针对群组中的每个元素进行评估,$maxN
保留最大n
值。n
限制群组的结果数量,并且n
必须是正整数表达式,它可以是常量或取决于$group
的_id
值。
行为
结果类型
$maxN
按照BSON比较顺序比较输入数据,以确定适当的输出类型。 当输入数据包含多种数据类型时, $maxN
输出类型是比较顺序中最高的类型。
Null 和缺失值
$maxN
过滤掉空值和缺失值。
考虑以下聚合,该聚合从群组中返回最多n
个文档:
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 } } } } ] )
在本例中:
$documents
创建包含玩家分数的字面文档。$group
按gameId
对文档进行分组。此示例只有一个gameId
、G1
。PlayerD
分数缺失,且PlayerE
的score
为空。这些值都被视为空值。maximumThreeScores
字段指定为带有input : "$score"
的$maxN
并作为数组返回。由于只有 3 个包含
scores
maxN
score
的文档,因此即使n = 4
, 也会返回最大 3 个字段。
[ { _id: 'G1', maximumThreeScores: [ 3, 2, 1 ] } ]
$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 } ])
找到单场游戏的最大三个Scores
您可以使用$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
返回n : 3
的G1
游戏的最大三个分数元素。
操作返回以下结果:
[ { _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
的值。 在此示例中,对gameId
字段使用了$cond
表达式。
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' ] ] } ]