文档菜单
文档首页
/
MongoDB 手册
/ / /

$minN(聚合累加器)

本页内容

  • 定义
  • 语法
  • 行为
  • 限制
  • 示例
$minN

在版本5.2.

返回组内最小值 n 个元素的聚合。如果组中元素少于 n 个,则 $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 缺少分数,而 PlayerEscore 为空。这两个值都被忽略。

  • 字段 minimumThreeScores 被指定为$minN,输入为 input : "$score",并以数组形式返回。

  • 由于只有3个文档包含 scores,因此即使 n = 4minN 也会返回最小的3个 score 字段。

[
{
_id: 'G1',
minimumThreeScores: [ 1, 2, 3 ]
}
]

两个累加器 $minN$bottomN 都可以完成类似的结果。

一般来说

  • $minN 有优势,可以在没有任何特定排序顺序的情况下找到最小值。如果你想知道前 n 个文档的最小值,请使用 $minN

  • 如果保证特定的排序顺序是必需的,请使用 $bottomN

  • 如果你不打算根据输出值进行排序,请使用 $bottomN

您可以将 $minN 作为累加器使用。

$minN 支持作为 聚合表达式

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

您还可以动态地分配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"]

  • 如果gameIdG2,则n为1,否则为3。

该操作返回以下结果

[
{ _id: { gameId: 'G2' }, gamescores: [ [ 10, 'PlayerA' ] ] },
{
_id: { gameId: 'G1' },
gamescores: [ [ 1, 'PlayerD' ], [ 31, 'PlayerA' ], [ 33, 'PlayerB' ] ]
}
]

返回

$min