$minN(聚合累加器)
定义
语法
{ $minN: { input: <expression>, n: <expression> } }
input
指定一个表达式,作为$minN
的输入。 系统会针对群组中的每个元素进行评估,而$minN
会保留最小n
值。n
限制群组的结果数量,并且n
必须是正整数表达式,它可以是常量或取决于$group
的_id
值。
行为
Null 和缺失值
$minN
过滤掉空值和缺失值。
考虑以下聚合,该聚合从组中返回最少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", minimumThreeScores: { $minN: { input: "$score", n: 4 } } } } ] )
在本例中:
$documents
创建包含玩家分数的字面文档。$group
按gameId
对文档进行分组。此示例只有一个gameId
、G1
。PlayerD
分数缺失,且PlayerE
的score
为空。 这些值都被忽略。minimumThreeScores
字段指定为带有input : "$score"
的$minN
并作为数组返回。由于只有 3 个具有 的文档,因此即使
scores
minN
score
n = 4
, 也会返回最少 3 个字段。
[ { _id: 'G1', minimumThreeScores: [ 1, 2, 3 ] } ]
$minN
和$bottomN
累加器的比较
一般来说:
如果要求保证特定的排序顺序,请使用
$bottomN
。如果不打算对输出值进行排序,请使用
$bottomN
。
限制
窗口函数和聚合表达式支持
您可以将$minN
用作累加器。
内存限制注意事项
调用 $minN
的聚合管道受 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
您可以使用$minN
累加器查找单个游戏中的最小三个分数。
db.gamescores.aggregate( [ { $match : { gameId : "G1" } }, { $group: { _id: "$gameId", minScores: { $minN: { input: ["$score","$playerId"], n:3 } } } } ] )
示例管道:
使用
$match
筛选单个gameId
的结果。在本例中为G1
。使用
$group
按gameId
对结果分组。本例中为G1
。指定使用
input : ["$score","$playerId"]
为$minN
输入的字段。使用
$minN
返回具有n : 3
的G1
游戏的前三个分数元素。
操作返回以下结果:
[ { _id: 'G1', minScores: [ [ 1, 'PlayerD' ], [ 31, 'PlayerA' ], [ 33, 'PlayerB' ] ] } ]
查找多个游戏中的最少三个文档
您可以使用$minN
累加器查找每场游戏中的最低n
分数。
db.gamescores.aggregate( [ { $group: { _id: "$gameId", minScores: { $minN: { input: ["$score","$playerId"], n: 3 } } } } ] )
示例管道:
使用
$group
按gameId
对结果进行分组。使用
$minN
返回每个具有n: 3
的游戏的最小三个分数元素。指定使用
input: ["$score","$playerId"]
为$minN
输入的字段。
操作返回以下结果:
[ { _id: 'G2', minScores: [ [ 10, 'PlayerA' ], [ 14, 'PlayerB' ], [ 66, 'PlayerC' ] ] }, { _id: 'G1', minScores: [ [ 1, 'PlayerD' ], [ 31, 'PlayerA' ], [ 33, 'PlayerB' ] ] } ]
根据n
的群组密钥计算$group
您还可以动态分配n
的值。 在此示例中,对gameId
字段使用了$cond
表达式。
db.gamescores.aggregate([ { $group: { _id: {"gameId": "$gameId"}, gamescores: { $minN: { input: ["$score","$playerId"], n: { $cond: { if: {$eq: ["$gameId","G2"] }, then: 1, else: 3 } } } } } } ] )
示例管道:
使用
$group
按gameId
对结果进行分组。指定使用
input : ["$score","$playerId"]
输入$minN
的字段。如果
gameId
为G2
,则n
为 1,否则n
为 3。
操作返回以下结果:
[ { _id: { gameId: 'G2' }, gamescores: [ [ 10, 'PlayerA' ] ] }, { _id: { gameId: 'G1' }, gamescores: [ [ 1, 'PlayerD' ], [ 31, 'PlayerA' ], [ 33, 'PlayerB' ] ] } ]