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