Docs 菜单
Docs 主页
/
MongoDB Manual
/ / /

$median(聚合)

在此页面上

  • 定义
  • 语法
  • 命令字段
  • 行为
  • 示例
  • 了解详情
$median

7.0 版本中的新增功能

以标量值的形式返回中位数(即第50个百分位数)的近似值。

您可以使用 $median 作为 $group 阶段的累加器聚合表达式

$median 的语法为:

{
$median: {
input: <number>,
method: <string>
}
}

$median 采用以下字段:

字段
类型
必要性
说明

input

表达式(expression)

必需

$median 计算此数据的第50个百分位数。 input必须是计算结果为数字类型的字段名或表达式。 如果表达式无法转换为数字类型, $median计算将忽略它。

method

字符串

必需

mongod 用于计算第 50 个百分位数的方法。该方法必须是 'approximate'

您可以在以下位置使用 $median

  • $group 阶段用作累加器

  • $setWindowFields 阶段用作累加器

  • $project 阶段作为聚合表达式

$median 作为累加器,具有以下特点:

  • 为阶段中的所有文档计算单独的结果。

  • 使用 t-digest 算法计算基于百分位数的近似指标。

  • 使用近似方法来扩展海量数据。

$median 作为聚合表达式,具有以下特点:

  • 接受数组作为输入

  • 为每个输入文档计算单独的结果

$group 阶段,$median 是累加器,计算窗口中所有文档的值。

$project 阶段,$median 是一个聚合表达式,用于计算每个文档的值。

$setWindowFields 阶段中,$median 像聚合表达式一样返回每个文档的结果,但该结果是通过诸如累加器之类的文档组计算得出的。

$group 阶段中,$median 始终使用近似计算方法。

$project 阶段,即使指定了近似方法,$median 也可能使用离散计算方法。

$setWindowFields 阶段,工作负载决定了 $median 使用的计算方法。

即使在相同的数据集上,计算出的 $median 收益的百分位数也可能不同。这是因为算法计算的是近似值。

重复样本可能会导致歧义。如果存在大量重复样本,百分位值可能无法代表实际的样本分布。考虑所有样本都相同的数据集。数据集中的所有值都位于或低于任何百分位数。“第 50 百分位数”的值实际上代表 0 或 100% 的样本。

如果在 $project 阶段使用 $median 作为聚合表达式,则可以使用数组作为输入。$median 会忽略非数字数组值。

语法为:

{
$median:
{
input: [ <expression1, <expression2>, ..., <expressionN> ],
method: <string>
}
}

通过窗口函数,您可以计算出相邻文档移动“窗口”的结果。当每份文档通过管道时,$setWindowFields 阶段:

  • 重新计算当前窗口中的文档集

  • 计算集合中所有文档的值

  • 返回该文档的单个值

您可以在 $setWindowFields 阶段使用 $median 来计算时间序列或其他相关数据的滚动统计数据。

$setWindowField 阶段使用 $median 时,input 值必须是字段名。如果输入数组而不是字段名称,则操作将失败。

以下示例使用 testScores 集合。创建集合:

db.testScores.insertMany( [
{ studentId: "2345", test01: 62, test02: 81, test03: 80 },
{ studentId: "2356", test01: 60, test02: 83, test03: 79 },
{ studentId: "2358", test01: 67, test02: 82, test03: 78 },
{ studentId: "2367", test01: 64, test02: 72, test03: 77 },
{ studentId: "2369", test01: 60, test02: 53, test03: 72 }
] )

创建计算中位数值的累加器:

db.testScores.aggregate( [
{
$group: {
_id: null,
test01_median: {
$median: {
input: "$test01",
method: 'approximate'
}
}
}
}
] )

输出:

{ _id: null, test01_median: 62 }

_id 字段值为 null,因此 $group 选择集合中的所有文档。

$median 累加器从 test01 字段获取输入数据。$median 计算该字段的中位数值,在本例中为 62

$group 阶段,$median 是累加器,计算所有文档的单个值。在 $project 阶段,$median 是一个聚合表达式,用于计算每个文档的值。

您可以在 $project 阶段使用字段名称或数组作为输入。

db.testScores.aggregate( [
{
$project: {
_id: 0,
studentId: 1,
testMedians: {
$median: {
input: [ "$test01", "$test02", "$test03" ],
method: 'approximate'
}
}
}
}
] )

输出:

{ studentId: '2345', testMedians: 80 },
{ studentId: '2356', testMedians: 79 },
{ studentId: '2358', testMedians: 78 },
{ studentId: '2367', testMedians: 72 },
{ studentId: '2369', testMedians: 60 }

$median 是聚合表达式时,每个 studentId 都有一个结果。

如需根据本地数据趋势确定百分位值,请使用 $setWindowField 聚合管道阶段的 $median

此示例创建了一个筛选分数的窗口:

db.testScores.aggregate( [
{
$setWindowFields: {
sortBy: { test01: 1 },
output: {
test01_median: {
$median: {
input: "$test01",
method: 'approximate'
},
window: {
range: [ -3, 3 ]
}
}
}
}
},
{
$project: {
_id: 0,
studentId: 1,
test01_median: 1
}
}
] )

输出:

{ studentId: '2356', test01_median: 60 },
{ studentId: '2369', test01_median: 60 },
{ studentId: '2345', test01_median: 60 },
{ studentId: '2367', test01_median: 64 },
{ studentId: '2358', test01_median: 64 }

在此示例中,每个文档的中位数计算还包含该文档之前和之后的三个文档的数据。

$percentile 操作符是 $median 操作符的更通用版本,可用于设置一个或多个百分位数值。

有关窗口函数的更多信息,请参阅:$setWindowFields

后退

$maxN-array-element