文章目录
- MongoDB聚合运算符:$linearFill
- 语法
- 使用
- 对比`$fill`和`$linearFill`
- 举例
- 使用线性插值填充缺失值
- 在单个阶段中使用多种填充方法
MongoDB聚合运算符:$linearFill
$linearFill
聚合运算符在一个窗口中基于附近字段的值使用线性插值填充null
和缺失字段。
语法
{ $linearFill: <expression> }
使用
$linearFill
聚合运算符在一个窗口中基于附近字段的非空值使用线性插值填充null
和缺失字段。附近字段值由$setWindowFields
的排序顺序决定。
-
$linearFill
按比例填充空值和缺失值,跨越周围非空值之间的数值范围,要确定缺失字段的值,$linearFill
使用:- 周围非空值的差值。
- 要填充周围值之间的空字段的数量。
-
$linearFill
如果根据$setWindowFields
中指定的排序顺序,前面和后面都有非空值,则可以填充多个连续的空值。
如果集合包含这些文档:{ index: 0, value: 0 }, { index: 1, value: null }, { index: 2, value: null }, { index: 3, value: null }, { index: 4, value: 10 }
使用
$linearFill
后为了填充空值,文档变成:{ index: 0, value: 0 }, { index: 1, value: 2.5 }, { index: 2, value: 5 }, { index: 3, value: 7.5 }, { index: 4, value: 10 }
-
前后都没有非空值的
null
仍为null
。
注意:
- 要使用
$linearFill
必须要使用sortBy
字段对数据进行排序。 - 当使用线性填充窗口功能时,如果单个分区中的
sortBy
字段中有任何重复值,$setWindowFields
将返回错误。
对比$fill
和$linearFill
使用$linearFill
填充缺失字段值时,可以:
- 在
$fill
阶段用{ method: "linear" }
。当使用$fill
阶段时,在输出中指定的字段与用作源数据的字段相同。 - 在
$setWindowFields
中使用$linearFill
操作符。可以为与用作源数据的字段不同的字段设置值。
举例
使用下面的脚本创建stock
集合,包含了每小时跟踪的单个公司的股票价格信息:
db.stock.insertMany( [{time: ISODate("2021-03-08T09:00:00.000Z"),price: 500},{time: ISODate("2021-03-08T10:00:00.000Z"),},{time: ISODate("2021-03-08T11:00:00.000Z"),price: 515},{time: ISODate("2021-03-08T12:00:00.000Z")},{time: ISODate("2021-03-08T13:00:00.000Z")},{time: ISODate("2021-03-08T14:00:00.000Z"),price: 485}
] )
集合中的某些文档缺少price
字段
使用线性插值填充缺失值
在$setWindowFields
阶段内部,使用$linearFill
线性插值填充缺失的price
字段值:
db.stock.aggregate( [{$setWindowFields:{sortBy: { time: 1 },output:{price: { $linearFill: "$price" }}}}
] )
在本例中:
sortBy: { time: 1 }
按time
字段从最早到最晚的升序对文档进行排序。output
指定了:price
作为要填充的缺失值的字段{ $linearFill: "$price" }
作为缺失字段的值。$linearFill
基于序列中price
周围的值使用线性插值来填充缺失的price
的值。
输出结果:
[{_id: ObjectId("620ad555394d47411658b5ef"),time: ISODate("2021-03-08T09:00:00.000Z"),price: 500},{_id: ObjectId("620ad555394d47411658b5f0"),time: ISODate("2021-03-08T10:00:00.000Z"),price: 507.5},{_id: ObjectId("620ad555394d47411658b5f1"),time: ISODate("2021-03-08T11:00:00.000Z"),price: 515},{_id: ObjectId("620ad555394d47411658b5f2"),time: ISODate("2021-03-08T12:00:00.000Z"),price: 505},{_id: ObjectId("620ad555394d47411658b5f3"),time: ISODate("2021-03-08T13:00:00.000Z"),price: 495},{_id: ObjectId("620ad555394d47411658b5f4"),time: ISODate("2021-03-08T14:00:00.000Z"),price: 485}
]
在单个阶段中使用多种填充方法
当使用$setWindowFields
阶段填充缺失值时,可以为与填充的字段不同的字段设置值,所以可以在单个$setWindowFields
阶段中使用多个填充方法,并将结果输出到不同的字段中。
下面的聚合管道使用线性插值和最后观测前移法填充缺失的price
字段的值:
db.stock.aggregate( [{$setWindowFields:{sortBy: { time: 1 },output:{linearFillPrice: { $linearFill: "$price" },locfPrice: { $locf: "$price" }}}}
] )
在本例中:
sortBy: { time: 1 }
按time
字段从最早到最晚的升序对文档进行排序。output
指定了:linearFillPrice
作为要填充的目标字段{ $linearFill: "$price" }
是LinearFillPrice
字段的值。$linearFill
基于序列中price
周围的值使用线性插值来填充缺失的price
的值。
locfPrice
作为要填充的目标字段{ $locf: "$price" }
为locfPrice
字段的值。locf
代表最后一次观察结果。$locf
使用序列中前一个文档中的值填充缺失的price
的值。
结果输出:
[{_id: ObjectId("620ad555394d47411658b5ef"),time: ISODate("2021-03-08T09:00:00.000Z"),price: 500,linearFillPrice: 500,locfPrice: 500},{_id: ObjectId("620ad555394d47411658b5f0"),time: ISODate("2021-03-08T10:00:00.000Z"),linearFillPrice: 507.5,locfPrice: 500},{_id: ObjectId("620ad555394d47411658b5f1"),time: ISODate("2021-03-08T11:00:00.000Z"),price: 515,linearFillPrice: 515,locfPrice: 515},{_id: ObjectId("620ad555394d47411658b5f2"),time: ISODate("2021-03-08T12:00:00.000Z"),linearFillPrice: 505,locfPrice: 515},{_id: ObjectId("620ad555394d47411658b5f3"),time: ISODate("2021-03-08T13:00:00.000Z"),linearFillPrice: 495,locfPrice: 515},{_id: ObjectId("620ad555394d47411658b5f4"),time: ISODate("2021-03-08T14:00:00.000Z"),price: 485,linearFillPrice: 485,locfPrice: 485}
]