$percentile (aggregation)
定义
语法
$percentile
的语法为:
{ $percentile: { input: <expression>, p: [ <expression1>, <expression2>, ... ], method: <string> } }
命令字段
$percentile
接受以下字段:
字段 | 类型 | 必要性 | 说明 |
---|---|---|---|
| 表达式(expression) | 必需 |
|
| 表达式(expression) | 必需 |
|
| 字符串 | 必需 | The method that |
行为
您可以在以下位置使用 $percentile
:
$group
阶段作为累加器$setWindowFields
阶段作为累加器作为聚合表达式的
$project
阶段
$percentile
作为累加器具有以下特征:
为阶段中的所有文档计算单独的结果。
使用 t-digest 算法计算近似的、基于百分位数的指标。
使用近似方法来扩展海量数据。
$percentile
作为聚合表达式具有以下特征:
接受数组作为输入
为每个输入文档计算单独的结果
操作类型
在 $group
阶段,$percentile
是累加器,计算窗口中所有文档的值。
在 $project
阶段,$percentile
是一个聚合表达式,用于计算每个文档的值。
在 $setWindowFields
阶段中,$percentile
像聚合表达式一样返回每个文档的结果,但该结果是通过诸如累加器之类的文档组计算得出的。
计算注意事项
在 $group
阶段中,$percentile
始终使用近似计算方法。
在 $project
阶段,即使指定了近似方法,$percentile
也可能使用离散计算方法。
在 $setWindowFields
阶段,工作负载决定了 $percentile
使用的计算方法。
即使在相同的数据集上,计算出的 $percentile
收益的百分位数也可能不同。这是因为算法计算的是近似值。
重复样本可能会导致歧义。如果存在大量重复样本,百分位值可能无法代表实际的样本分布。考虑所有样本都相同的数据集。数据集中的所有值都位于或低于任何百分位数。“第 50 百分位数”的值实际上代表 0 或 100% 的样本。
$percentile
returns the minimum value for p = 0.0
.
$percentile
returns the maximum value for p = 1.0
.
数组输入
If you use $percentile
as an aggregation expression in a
$project
stage, you can use an array as input.
The syntax is:
{ $percentile: { input: [ <expression1, <expression2>, .., <expressionN> ], p: [ <expression1>, <expression2>, ... ], method: <string> } }
窗口功能
通过窗口函数,您可以计算出相邻文档移动“窗口”的结果。当每份文档通过管道时,$setWindowFields
阶段:
重新计算当前窗口中的文档集
计算集合中所有文档的值
返回该文档的单个值
您可以在 $setWindowFields
阶段使用 $percentile
来计算时间序列或其他相关数据的滚动统计数据。
在 $setWindowField
阶段使用 $percentile
时,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 } ] )
Calculate a Single Value as an Accumulator
Create an accumulator that calculates a single percentile value:
db.testScores.aggregate( [ { $group: { _id: null, test01_percentiles: { $percentile: { input: "$test01", p: [ 0.95 ], method: 'approximate' } }, } } ] )
输出:
{ _id: null, test01_percentiles: [ 67 ] }
_id
字段值为 null
,因此 $group
选择集合中的所有文档。
The percentile
accumulator takes its input data from the test01
field.
In this example, the percentiles array, p
, has one value so the
$percentile
operator only calculates one term for the test01
data. The 95th percentile value is 67
.
Calculate Multiple Values as an Accumulator
Create an accumulator that calculates multiple percentile values:
db.testScores.aggregate( [ { $group: { _id: null, test01_percentiles: { $percentile: { input: "$test01", p: [ 0.5, 0.75, 0.9, 0.95 ], method: 'approximate' } }, test02_percentiles: { $percentile: { input: "$test02", p: [ 0.5, 0.75, 0.9, 0.95 ], method: 'approximate' } }, test03_percentiles: { $percentile: { input: "$test03", p: [ 0.5, 0.75, 0.9, 0.95 ], method: 'approximate' } }, test03_percent_alt: { $percentile: { input: "$test03", p: [ 0.9, 0.5, 0.75, 0.95 ], method: 'approximate' } }, } } ] )
输出:
{ _id: null, test01_percentiles: [ 62, 64, 67, 67 ], test02_percentiles: [ 81, 82, 83, 83 ], test03_percentiles: [ 78, 79, 80, 80 ], test03_percent_alt: [ 80, 78, 79, 80 ] }
_id
字段值为 null
,因此 $group
选择集合中的所有文档。
The percentile
accumulator calculates values for three fields,
test01
, test02
, and test03
.
The accumulator calculates the 50th, 75th, 90th, and 95th percentile values for each input field.
The percentile values are returned in the same order as the elements of
p
. The values in test03_percentiles
and test03_percent_alt
are the same, but their order is different. The order of elements in
each result array matches the corresponding order of elements in p
.
在 $project
阶段使用 $percentile
在 $project
阶段,$percentile
是一个聚合表达式,用于计算每个文档的值。
您可以在 $project
阶段使用字段名称或数组作为输入。
db.testScores.aggregate( [ { $project: { _id: 0, studentId: 1, testPercentiles: { $percentile: { input: [ "$test01", "$test02", "$test03" ], p: [ 0.5, 0.95 ], method: 'approximate' } } } } ] )
输出:
{ studentId: '2345', testPercentiles: [ 80, 81 ] }, { studentId: '2356', testPercentiles: [ 79, 83 ] }, { studentId: '2358', testPercentiles: [ 78, 82 ] }, { studentId: '2367', testPercentiles: [ 72, 77 ] }, { studentId: '2369', testPercentiles: [ 60, 72 ] }
当 $percentile
是聚合表达式时,每个 studentId
都有一个结果。
在 $setWindowField
阶段使用 $percentile
如需根据本地数据趋势确定百分位值,请使用 $setWindowField
聚合管道阶段的 $percentile
。
此示例创建了一个筛选分数的窗口:
db.testScores.aggregate( [ { $setWindowFields: { sortBy: { test01: 1 }, output: { test01_95percentile: { $percentile: { input: "$test01", p: [ 0.95 ], method: 'approximate' }, window: { range: [ -3, 3 ] } } } } }, { $project: { _id: 0, studentId: 1, test01_95percentile: 1 } } ] )
输出:
{ studentId: '2356', test01_95percentile: [ 62 ] }, { studentId: '2369', test01_95percentile: [ 62 ] }, { studentId: '2345', test01_95percentile: [ 64 ] }, { studentId: '2367', test01_95percentile: [ 67 ] }, { studentId: '2358', test01_95percentile: [ 67 ] }
In this example, the percentile calculation for each document also incorporates data from the three documents before and after it.
了解详情
The $median
operator is a special case of the
$percentile
operator that uses a fixed value of p: [ 0.5 ]
.
有关窗口函数的更多信息,请参阅:$setWindowFields
。