本文主要是介绍MongoDB聚合运算符:$median,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 语法
- 参数字段
- 使用
- 类型操作
- 计算注意事项
- 数组处理
- 窗口函数
- 举例
- $median作为累加器
- 在 p r o j e c t 阶段使用 project阶段使用 project阶段使用median
- 在`$setWindowField`阶段使用`$median`
$median
聚合运算符以标量值返回中位数的近似值,即第50百分位数。$median
可以在$group
阶段的累加器或聚合表达式使用。
语法
{$median: {input: <number>,method: <string>}
}
参数字段
- input:必须的参数字段,数值类型的字段或表达式,指定要计算中位数的值,如果值不是字符类型,在计算式会被忽略。
- method:字符串或字符串表达式,指定中位数的计算方法,其值必须为
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
时,输入值必须是字段名,如果输入的是数组而不是字段名,操作将失败。
举例
使用下面的脚本创建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
字段的值为空,所以$group
选择了集合中的所有文档。
$median
累加器用test01
字段作为输入字段,计算出字段的中位数为62
。
在 p r o j e c t 阶段使用 project阶段使用 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 }
下面的聚合操作使用$median
运算符来判断qty
是否小于250
:
db.inventory.aggregate([{$project:{item: 1,qty: 1,qtyLt250: { $median: [ "$qty", 250 ] },_id: 0}}]
)
操作返回下面的结果:
{ "item" : "abc1", "qty" : 300, "qtyLt250" : false }
{ "item" : "abc2", "qty" : 200, "qtyLt250" : true }
{ "item" : "xyz1", "qty" : 250, "qtyLt250" : false }
{ "item" : "VWZ1", "qty" : 300, "qtyLt250" : false }
{ "item" : "VWZ2", "qty" : 180, "qtyLt250" : true }
这篇关于MongoDB聚合运算符:$median的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!