中位数(聚合)
定义
语法
$median
的语法是
{ $median: { input: <number>, method: <string> } }
命令字段
$median
以下字段
字段 | 类型 | 必需性 | 描述 |
---|---|---|---|
input | 表达式 | 必需 | $median 计算数据的第50个百分位数。 input 必须是字段名或评估为数值类型的表达式。如果表达式不能转换为数值类型,则 $median 计算会忽略它。 |
method | 字符串 | 必需 | mongod计算第50百分位数的方法。该方法必须是 'approximate' 。 |
行为
您可以在
$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 } ] )
将 $median
用作累加器
创建一个计算中值值的累加器
db.testScores.aggregate( [ { $group: { _id: null, test01_median: { $median: { input: "$test01", method: 'approximate' } } } } ] )
输出
{ _id: null, test01_median: 62 }
_id
字段值为 null
因此 $group
选择集合中的所有文档。
$median
累加器从 test01
字段获取输入。在此示例中,$median
计算了该字段的median值,即 62
。
在 $project
阶段使用 $median
。详情请见
在 $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
。详情请见
要基于本地数据趋势建立您的百分位数值,请在 $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
。