$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' ] ] } ]