$minN(聚合累加器)
定义
语法
{ $minN: { input: <expression>, n: <expression> } }
input指定一个表达式,它是$minN的输入。它对组中的每个元素进行评估,并且$minN保留最小的n个值。n限制每个组的输出结果数量,并且n必须是一个正整数表达式,它可以是常数或依赖于_id值的$group.
行为
结果类型
$minN 根据BSON比较顺序比较输入数据,以确定合适的输出类型。当输入数据包含多个数据类型时,$minN 的输出类型是比较顺序中的最低类型。。
空值和缺失值
$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被指定为$minN,输入为input : "$score",并以数组形式返回。由于只有3个文档包含
scores,因此即使n = 4,minN也会返回最小的3个score字段。
[ { _id: 'G1', minimumThreeScores: [ 1, 2, 3 ] } ]
比较 $minN 和 $bottomN 累加器
两个累加器 $minN 和 $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 } ])
查找单个游戏的最低三个 分数
您可以使用累加器 $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来返回G1游戏的前三个分数元素,其中n : 3。
该操作返回以下结果
[ { _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。指定输入给
$minN的字段,其中input: ["$score","$playerId"]。
该操作返回以下结果
[ { _id: 'G2', minScores: [ [ 10, 'PlayerA' ], [ 14, 'PlayerB' ], [ 66, 'PlayerC' ] ] }, { _id: 'G1', minScores: [ [ 1, 'PlayerD' ], [ 31, 'PlayerA' ], [ 33, 'PlayerB' ] ] } ]
根据$group的分组键计算n。
您还可以动态地分配n的值。在此示例中,使用$cond表达式对gameId字段进行操作。
db.gamescores.aggregate([ { $group: { _id: {"gameId": "$gameId"}, gamescores: { $minN: { input: ["$score","$playerId"], n: { $cond: { if: {$eq: ["$gameId","G2"] }, then: 1, else: 3 } } } } } } ] )
示例管道
使用
$group来根据gameId对结果进行分组。指定输入给
$minN的字段,其中input : ["$score","$playerId"]。如果
gameId是G2,则n为1,否则为3。
该操作返回以下结果
[ { _id: { gameId: 'G2' }, gamescores: [ [ 10, 'PlayerA' ] ] }, { _id: { gameId: 'G1' }, gamescores: [ [ 1, 'PlayerD' ], [ 31, 'PlayerA' ], [ 33, 'PlayerB' ] ] } ]