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

$percentile (聚合)

在本页中

  • 定义
  • 语法
  • 命令字段
  • 行为
  • 示例
  • 了解更多
$percentile

版本7.0.

返回一个与指定百分位数值对应的标量值数组。

您可以在累加器阶段或作为聚合表达式使用 $percentile

$percentile 的语法如下

{
$percentile: {
input: <expression>,
p: [ <expression1>, <expression2>, ... ],
method: <string>
}
}

$percentile 以下字段

字段
类型
必需性
描述
input
表达式
必需
$percentile 计算此数据的百分位数。 input 必须是字段名或计算结果为数值类型的表达式。如果表达式无法转换为数值类型,则 $percentile 计算会忽略它。
p
表达式
必需

$percentilep 中的每个元素计算百分位数。元素代表百分比,必须评估为范围在 0.01.0 之间的数值。

$percentile 返回的结果顺序与 p 中的元素顺序相同。

method
字符串
必需
mongod 计算百分位数所使用的方法。方法必须是 'approximate'

您可以在

  • $group阶段作为累加器使用

  • $setWindowFields阶段作为累加器使用

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

$percentile作为累加器具有以下特性:

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

  • 使用t-digest算法来计算基于百分比的近似度量。

  • 使用近似方法扩展到大量数据。

$percentile作为聚合表达式具有以下特性:

  • 接受数组作为输入

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

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

$project阶段中,$percentile是一个聚合表达式,为每个文档计算值。

$setWindowFields 阶段中,$percentile 返回类似于聚合表达式的每个文档的结果,但结果是在文档组上计算的,就像累加器。

$group 阶段中,$percentile 总是使用近似计算方法。

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

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

返回的计算的百分位数可能会变化,即使在相同的数据集上。这是因为算法计算近似值。

重复样本可能导致歧义。如果有大量重复的样本,百分位数可能不会代表实际的样本分布。考虑一个所有样本都相同的数据集。数据集中的所有值都处于或低于任何百分位数。实际的“50百分位数”值将代表0或100的样本百分比。

$percentile 返回 p = 0.0 的最小值。

$percentile 返回 p = 1.0 的最大值。

如果您将 $percentile 作为聚合表达式在 $project 阶段中使用,您可以使用数组作为输入。语法是

{
$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 }
] )

创建一个累加器,计算单个百分比值

db.testScores.aggregate( [
{
$group: {
_id: null,
test01_percentiles: {
$percentile: {
input: "$test01",
p: [ 0.95 ],
method: 'approximate'
}
},
}
}
] )

输出

{ _id: null, test01_percentiles: [ 67 ] }

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

percentile 累加器从 test01 字段获取输入数据。

在这个例子中,百分位数数组 p 只有一个值,所以 $percentile 操作符只为 test01 数据计算一个项。第95个百分位数的值是 67

创建一个计算多个百分位数值的累加器

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 选择集合中的所有文档。

percentile 累加器为三个字段 test01test02test03 计算值。

累加器计算每个输入字段的第50个、第75个、第90个和第95个百分位数值。

百分位数值以与 p 元素相同的顺序返回。在 test03_percentilestest03_percent_alt 中的值相同,但它们的顺序不同。每个结果数组中元素的顺序与 p 中对应元素的顺序相匹配。

$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

此示例创建一个窗口以过滤分数

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

在此示例中,每个文档的百分位数计算还结合了其前后三份文档的数据。

操作符 $median 是操作符 $percentile 的一个特例,使用固定的值 p: [ 0.5 ]

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

返回