Definition定义
$setWindowFields
5.0版本中的新功能。New in version 5.0.在版本5.0中新增。
Performs operations on a specified span of documents in a collection, known as a window, and returns the results based on the chosen window operator.对集合(称为窗口)中指定范围的文档执行操作,并根据所选的窗口运算符返回结果。
For example, you can use the 例如,您可以使用$setWindowFields stage to output the:$setWindowFields阶段输出:
Difference in sales between two documents in a collection.收款中两份单据之间的销售额差异。Sales rankings.销售排名。Cumulative sales totals.累计销售总额。Analysis of complex time series information without exporting the data to an external database.分析复杂的时间序列信息,而无需将数据导出到外部数据库。
Syntax语法
The $setWindowFields stage syntax:$setWindowFields阶段语法:
{
$setWindowFields: {
partitionBy: <expression>,
sortBy: {
<sort field 1>: <sort order>,
<sort field 2>: <sort order>,
...,
<sort field n>: <sort order>
},
output: {
<output field 1>: {
<window operator>: <window operator parameters>,
window: {
documents: [ <lower boundary>, <upper boundary> ],
range: [ <lower boundary>, <upper boundary> ],
unit: <time unit>
}
},
<output field 2>: { ... },
...
<output field n>: { ... }
}
}
}
The $setWindowFields stage takes a document with these fields:$setWindowFields阶段接收具有以下字段的文档:
partitionBy |
| |
sortBy |
| |
output |
| |
window |
| |
documents |
| |
range |
| |
unit |
|
Tip
Behavior行为
The $setWindowFields stage appends new fields to existing documents. You can include one or more $setWindowFields stages in an aggregation operation.$setWindowFields阶段将新字段附加到现有文档中。您可以在聚合操作中包含一个或多个$setWindowFields阶段。
Starting in MongoDB 5.3, you can use the 从MongoDB 5.3开始,您可以将$setWindowFields stage with transactions and the "snapshot" read concern.$setWindowFields阶段与事务和"snapshot"读取关注一起使用。
The $setWindowFields stage doesn't guarantee the order of the returned documents.$setWindowFields阶段不保证返回文档的顺序。
Window Operators窗口运算符
These operators can be used with the 这些运算符可以与$setWindowFields stage:$setWindowFields阶段一起使用:
Accumulator operators:累加器运算符:$addToSet,$avg,$bottom,$bottomN,$concatArrays,$count,$covariancePop,$covarianceSamp,$derivative,$expMovingAvg,$firstN,$integral,$lastN,$max,$maxN,$median,$min,$minN,$percentile,$push,$setUnion,$stdDevSamp,$stdDevPop,$sum,$top,$topN.
Gap filling operators:填隙运算符:$linearFilland$locf.
Rank operators:排名运算符:$denseRank,$documentNumber, and$rank.Range operator:量程运算符:$minMaxScaler
Restrictions限制
Restrictions for the $setWindowFields stage:$setWindowFields阶段的限制:
Prior to MongoDB 5.3, the在MongoDB 5.3之前,不能使用$setWindowFieldsstage cannot be used:$setWindowFields阶段:Within transactions.在事务中。With带有"snapshot"read concern."snapshot"读取关注。
以下情况需要sortByis required for:sortBy:Range windows require all sortBy values to be numbers.范围窗口要求所有sortBy值都是数字。Time range时间范围windows require all窗口要求所有sortByvalues to be dates.sortBy值都是日期。Range范围and和time range时间范围windows can only contain one sortBy field and the sort must be ascending.窗口只能包含一个sortBy字段,排序必须是升序。You cannot specify both a documents window and a range window.您不能同时指定documents窗口和范围窗口。These operators use an implicit window and return an error if you specify a window option:这些运算符使用隐式窗口,如果指定window选项,则返回错误:For range windows, only numbers in the specified range are included in the window. Missing, undefined, and对于范围窗口,窗口中只包含指定范围内的数字。缺失、未定义和nullvalues are excluded.null值被排除在外。For time range windows:对于时间范围窗口:Only date and time types are included in the window.窗口中仅包含日期和时间类型。Numeric boundary values must be integers. For example, you can use 2 hours as a boundary but you cannot use 1.5 hours.数值边界值必须是整数。例如,您可以使用2小时作为边界,但不能使用1.5小时。
For empty windows or windows with incompatible values (for example, using对于空窗口或具有不兼容值的窗口(例如,在字符串上使用$sumon strings), the returned value depends on the operator:$sum),返回值取决于运算符:
Examples示例
MongoDB Shell
Create a 创建一个cakeSales collection that contains cake sales in the states of California (CA) and Washington (WA):cakeSales集合,其中包含加利福尼亚州(CA)和华盛顿州(WA)的蛋糕销售:
db.cakeSales.insertMany( [
{ _id: 0, type: "chocolate", orderDate: new Date("2020-05-18T14:10:30Z"),
state: "CA", price: 13, quantity: 120 },
{ _id: 1, type: "chocolate", orderDate: new Date("2021-03-20T11:30:05Z"),
state: "WA", price: 14, quantity: 140 },
{ _id: 2, type: "vanilla", orderDate: new Date("2021-01-11T06:31:15Z"),
state: "CA", price: 12, quantity: 145 },
{ _id: 3, type: "vanilla", orderDate: new Date("2020-02-08T13:13:23Z"),
state: "WA", price: 13, quantity: 104 },
{ _id: 4, type: "strawberry", orderDate: new Date("2019-05-18T16:09:01Z"),
state: "CA", price: 41, quantity: 162 },
{ _id: 5, type: "strawberry", orderDate: new Date("2019-01-08T06:12:03Z"),
state: "WA", price: 43, quantity: 134 }
] )
The following examples use the 以下示例使用cakeSales collection.cakeSales集合。
Documents Window Examples文档窗口示例
Use Documents Window to Obtain Cumulative Quantity for Each State使用文档窗口获取每个州的累计数量
This example uses a documents window in 此示例使用$setWindowFields to output the cumulative cake sales quantity for each state:$setWindowFields中的documents窗口输出每个state(州)的累计蛋糕销售quantity(数量):
db.cakeSales.aggregate( [
{
$setWindowFields: {
partitionBy: "$state",
sortBy: { orderDate: 1 },
output: {
cumulativeQuantityForState: {
$sum: "$quantity",
window: {
documents: [ "unbounded", "current" ]
}
}
}
}
}
] )
In the example:在示例中:
partitionBy: "$state"partitions the documents in the collection by按state. There are partitions forCAandWA.state(州)对集合中的文档进行分区。CA和WA有分区。sortBy: { orderDate: 1 }sorts the documents in each partition by按orderDatein ascending order (1), so the earliestorderDateis first.orderDate升序(1)对每个分区中的文档进行排序,因此最早的orderDate位居前列。
output:Sets the将cumulativeQuantityForStatefield to the cumulativequantityfor eachstate, which increases by successive additions to the previous value in the partition.cumulativeQuantityForState字段设置为每个state的累积数量,该quantity通过连续添加到分区中的前一个值而增加。Calculates the cumulative使用在quantityusing the$sumoperator run in a documents window.documents窗口中运行的$sum运算符计算累计quantity。
The window contains documents between an该unboundedlower limit and thecurrentdocument.window包含介于unbounded下限和current文档之间的文档。This means这意味着$sumreturns the cumulativequantityfor the documents between the beginning of the partition and the current document.$sum返回从分区开始到当前文档之间的文档的累积quantity。
In this example output, the cumulative 在此示例输出中,quantity for CA and WA is shown in the cumulativeQuantityForState field:CA和WA的累积quantity显示在accumulateQuantityForState字段中:
{ "_id" : 4, "type" : "strawberry", "orderDate" : ISODate("2019-05-18T16:09:01Z"),
"state" : "CA", "price" : 41, "quantity" : 162, "cumulativeQuantityForState" : 162 }
{ "_id" : 0, "type" : "chocolate", "orderDate" : ISODate("2020-05-18T14:10:30Z"),
"state" : "CA", "price" : 13, "quantity" : 120, "cumulativeQuantityForState" : 282 }
{ "_id" : 2, "type" : "vanilla", "orderDate" : ISODate("2021-01-11T06:31:15Z"),
"state" : "CA", "price" : 12, "quantity" : 145, "cumulativeQuantityForState" : 427 }
{ "_id" : 5, "type" : "strawberry", "orderDate" : ISODate("2019-01-08T06:12:03Z"),
"state" : "WA", "price" : 43, "quantity" : 134, "cumulativeQuantityForState" : 134 }
{ "_id" : 3, "type" : "vanilla", "orderDate" : ISODate("2020-02-08T13:13:23Z"),
"state" : "WA", "price" : 13, "quantity" : 104, "cumulativeQuantityForState" : 238 }
{ "_id" : 1, "type" : "chocolate", "orderDate" : ISODate("2021-03-20T11:30:05Z"),
"state" : "WA", "price" : 14, "quantity" : 140, "cumulativeQuantityForState" : 378 }Use Documents Window to Obtain Cumulative Quantity for Each Year使用文档窗口获取每年的累计数量
This example uses a documents window in 此示例使用$setWindowFields to output the cumulative cake sales quantity for each $year in orderDate:$setWindowFields中的documents窗口输出orderDate中每个$year的累计蛋糕销售quantity:
db.cakeSales.aggregate( [
{
$setWindowFields: {
partitionBy: { $year: "$orderDate" },
sortBy: { orderDate: 1 },
output: {
cumulativeQuantityForYear: {
$sum: "$quantity",
window: {
documents: [ "unbounded", "current" ]
}
}
}
}
}
] )
In the example:在示例中:
partitionBy: { $year: "$orderDate" }partitions the documents in the collection by按$yearinorderDate. There are are partitions for2019,2020, and2021.$year按orderDate对集合中的文档进行分区。2019年、2020年和2021年有分区。sortBy: { orderDate: 1 }sorts the documents in each partition by按orderDatein ascending order (1), so the earliestorderDateis first.orderDate升序(1)对每个分区中的文档进行排序,因此最早的orderDate位居前列。output:Sets the将cumulativeQuantityForYearfield to the cumulativequantityfor each year, which increases by successive additions to the previous value in the partition.cumulativeQuantityForYear字段设置为每年的累积quantity,该数量通过连续添加到分区中的上一个值而增加。Calculates the cumulative使用在quantityusing the$sumoperator run in a documents window.documents窗口中运行的$sum运算符计算累计quantity。
The window contains documents between an该unboundedlower limit and thecurrentdocument. This means$sumreturns the cumulativequantityfor the documents between the beginning of the partition and the current document.window包含介于unbounded下限和current文档之间的文档。这意味着$sum返回从分区开始到当前文档之间的文档的累积quantity。
In this example output, the cumulative 在此示例输出中,每年的累积quantity for each year is shown in the cumulativeQuantityForYear field:quantity显示在cumulativeQuantityForYear字段中:
{ "_id" : 5, "type" : "strawberry", "orderDate" : ISODate("2019-01-08T06:12:03Z"),
"state" : "WA", "price" : 43, "quantity" : 134, "cumulativeQuantityForYear" : 134 }
{ "_id" : 4, "type" : "strawberry", "orderDate" : ISODate("2019-05-18T16:09:01Z"),
"state" : "CA", "price" : 41, "quantity" : 162, "cumulativeQuantityForYear" : 296 }
{ "_id" : 3, "type" : "vanilla", "orderDate" : ISODate("2020-02-08T13:13:23Z"),
"state" : "WA", "price" : 13, "quantity" : 104, "cumulativeQuantityForYear" : 104 }
{ "_id" : 0, "type" : "chocolate", "orderDate" : ISODate("2020-05-18T14:10:30Z"),
"state" : "CA", "price" : 13, "quantity" : 120, "cumulativeQuantityForYear" : 224 }
{ "_id" : 2, "type" : "vanilla", "orderDate" : ISODate("2021-01-11T06:31:15Z"),
"state" : "CA", "price" : 12, "quantity" : 145, "cumulativeQuantityForYear" : 145 }
{ "_id" : 1, "type" : "chocolate", "orderDate" : ISODate("2021-03-20T11:30:05Z"),
"state" : "WA", "price" : 14, "quantity" : 140, "cumulativeQuantityForYear" : 285 }Use Documents Window to Obtain Moving Average Quantity for Each Year使用文档窗口获取每年的移动平均数量
This example uses a documents window in 此示例使用$setWindowFields to output the moving average for the cake sales quantity:$setWindowFields中的documents窗口输出蛋糕销售quantity的移动平均值:
db.cakeSales.aggregate( [
{
$setWindowFields: {
partitionBy: { $year: "$orderDate" },
sortBy: { orderDate: 1 },
output: {
averageQuantity: {
$avg: "$quantity",
window: {
documents: [ -1, 0 ]
}
}
}
}
}
] )
In the example:在示例中:
partitionBy: "$orderDate"partitions the documents in the collection by按$yearinorderDate. There are are partitions for2019,2020, and2021.$year按orderDate对集合中的文档进行分区。2019年、2020年和2021年有分区。sortBy: { orderDate: 1 }sorts the documents in each partition by按orderDatein ascending order (1), so the earliestorderDateis first.orderDate升序(1)对每个分区中的文档进行排序,因此最早的orderDate位居前列。output:Sets the将averageQuantityfield to the moving averagequantityfor each year.averageQuantity字段设置为每年的移动平均quantity。Calculates the moving average使用在quantityusing the$avgoperator run in a documents window.documents窗口中运行的$avg运算符计算移动平均quantity。
The window contains documents between-1and0.window包含介于-1和0之间的文档。This means这意味着$avgreturns the moving averagequantitybetween the document before the current document (-1) and the current document (0) in the partition.$avg返回分区中当前文档之前的文档(-1)和当前文档(0)之间的移动平均quantity。
In this example output, the moving average 在此示例输出中,移动平均quantity is shown in the averageQuantity field:quantity显示在averageQuantity字段中:
{ "_id" : 5, "type" : "strawberry", "orderDate" : ISODate("2019-01-08T06:12:03Z"),
"state" : "WA", "price" : 43, "quantity" : 134, "averageQuantity" : 134 }
{ "_id" : 4, "type" : "strawberry", "orderDate" : ISODate("2019-05-18T16:09:01Z"),
"state" : "CA", "price" : 41, "quantity" : 162, "averageQuantity" : 148 }
{ "_id" : 3, "type" : "vanilla", "orderDate" : ISODate("2020-02-08T13:13:23Z"),
"state" : "WA", "price" : 13, "quantity" : 104, "averageQuantity" : 104 }
{ "_id" : 0, "type" : "chocolate", "orderDate" : ISODate("2020-05-18T14:10:30Z"),
"state" : "CA", "price" : 13, "quantity" : 120, "averageQuantity" : 112 }
{ "_id" : 2, "type" : "vanilla", "orderDate" : ISODate("2021-01-11T06:31:15Z"),
"state" : "CA", "price" : 12, "quantity" : 145, "averageQuantity" : 145 }
{ "_id" : 1, "type" : "chocolate", "orderDate" : ISODate("2021-03-20T11:30:05Z"),
"state" : "WA", "price" : 14, "quantity" : 140, "averageQuantity" : 142.5 }Use Documents Window to Obtain Cumulative and Maximum Quantity for Each Year使用文档窗口获取每年的累计和最大数量
This example uses a documents window in 此示例使用$setWindowFields to output the cumulative and maximum cake sales quantity values for each $year in orderDate:$setWindowFields中的documents窗口输出orderDate中每个$year的累计和最大蛋糕销售quantity值:
db.cakeSales.aggregate( [
{
$setWindowFields: {
partitionBy: { $year: "$orderDate" },
sortBy: { orderDate: 1 },
output: {
cumulativeQuantityForYear: {
$sum: "$quantity",
window: {
documents: [ "unbounded", "current" ]
}
},
maximumQuantityForYear: {
$max: "$quantity",
window: {
documents: [ "unbounded", "unbounded" ]
}
}
}
}
}
] )
In the example:在示例中:
partitionBy: "$orderDate"partitions the documents in the collection by按$yearinorderDate. There are are partitions for2019,2020, and2021.$year按orderDate对集合中的文档进行分区。2019年、2020年和2021年有分区。sortBy: { orderDate: 1 }sorts the documents in each partition by按orderDatein ascending order (1), so the earliestorderDateis first.orderDate升序(1)对每个分区中的文档进行排序,因此最早的orderDate位居前列。output:Sets the将cumulativeQuantityForYearfield to the cumulativequantityfor each year.cumulativeQuantityForYear字段设置为每年的累积quantity。Calculates the cumulative使用在quantityusing the$sumoperator run in a documents window.documents窗口中运行的$sum运算符计算累计quantity。The window contains documents between an该unboundedlower limit and thecurrentdocument.window包含介于unbounded下限和current文档之间的文档。This means这意味着$sumreturns the cumulative quantity for the documents between the beginning of the partition and the current document.$sum返回从分区开始到当前文档之间的文档的累积数量。Sets the将maximumQuantityForYearfield to the maximumquantityfor each year.maximumQuantityForYear字段设置为每年的最大quantity。Calculates the maximum使用在quantityof all the documents using the$maxoperator run in a documents window.documents窗口中运行的$max运算符计算所有文档的最大quantity。
The window contains documents between an该unboundedlower andupperlimit.window包含在unbounded下限和unbounded上限之间的文档。This means这意味着$maxreturns the maximum quantity for the documents in the partition.$max返回分区中文档的最大数量。
In this example output, the cumulative 在此示例输出中,累积quantity is shown in the cumulativeQuantityForYear field and the maximum quantity is shown in the maximumQuantityForYear field:quantity显示在cumulativeQuantityForYear字段中,最大quantity显示在maximumQuantityForYear字段中:
{ "_id" : 5, "type" : "strawberry", "orderDate" : ISODate("2019-01-08T06:12:03Z"),
"state" : "WA", "price" : 43, "quantity" : 134,
"cumulativeQuantityForYear" : 134, "maximumQuantityForYear" : 162 }
{ "_id" : 4, "type" : "strawberry", "orderDate" : ISODate("2019-05-18T16:09:01Z"),
"state" : "CA", "price" : 41, "quantity" : 162,
"cumulativeQuantityForYear" : 296, "maximumQuantityForYear" : 162 }
{ "_id" : 3, "type" : "vanilla", "orderDate" : ISODate("2020-02-08T13:13:23Z"),
"state" : "WA", "price" : 13, "quantity" : 104,
"cumulativeQuantityForYear" : 104, "maximumQuantityForYear" : 120 }
{ "_id" : 0, "type" : "chocolate", "orderDate" : ISODate("2020-05-18T14:10:30Z"),
"state" : "CA", "price" : 13, "quantity" : 120,
"cumulativeQuantityForYear" : 224, "maximumQuantityForYear" : 120 }
{ "_id" : 2, "type" : "vanilla", "orderDate" : ISODate("2021-01-11T06:31:15Z"),
"state" : "CA", "price" : 12, "quantity" : 145,
"cumulativeQuantityForYear" : 145, "maximumQuantityForYear" : 145 }
{ "_id" : 1, "type" : "chocolate", "orderDate" : ISODate("2021-03-20T11:30:05Z"),
"state" : "WA", "price" : 14, "quantity" : 140,
"cumulativeQuantityForYear" : 285, "maximumQuantityForYear" : 145 }Range Window Example范围窗口示例
This example uses a range window in 此示例使用$setWindowFields to return the sum of the quantity values of cakes sold for orders within plus or minus 10 dollars of the current document's price value:$setWindowFields中的一个range窗口返回当前文档价格值正负10美元范围内的订单所售蛋糕数量值的总和:
db.cakeSales.aggregate( [
{
$setWindowFields: {
partitionBy: "$state",
sortBy: { price: 1 },
output: {
quantityFromSimilarOrders: {
$sum: "$quantity",
window: {
range: [ -10, 10 ]
}
}
}
}
}
] )
In the example:在示例中:
partitionBy: "$state"partitions the documents in the collection by按state. There are partitions forCAandWA.state对集合中的文档进行分区。CA和WA有分区。sortBy: { price: 1 }sorts the documents in each partition by按pricein ascending order (1), so the lowestpriceis first.price升序(1)对每个分区中的文档进行排序,因此最低price位居前列。outputsets the将quantityFromSimilarOrdersfield to the sum of thequantityvalues from the documents in a range window.quantityFromSimilarOrders字段设置为range窗口中文档的quantity值之和。The window contains documents between a lower limit of该-10and an upper limit of10. The range is inclusive.window包含下限-10和上限10之间的文档。范围是包含性的。$sumreturns the sum of返回当前文档quantityvalues contained in a range of plus or minus 10 dollars of the current document'spricevalue.price值正负10美元范围内包含的quantity值的总和。
In this example output, the sum of the 在此示例输出中,窗口中文档的quantity values for documents in the window is shown in the quantityFromSimilarOrders field:quantity值之和显示在quantityFromSimilarOrders字段中:
{ "_id" : 2, "type" : "vanilla", "orderDate" : ISODate("2021-01-11T06:31:15Z"),
"state" : "CA", "price" : 12, "quantity" : 145, "quantityFromSimilarOrders" : 265 }
{ "_id" : 0, "type" : "chocolate", "orderDate" : ISODate("2020-05-18T14:10:30Z"),
"state" : "CA", "price" : 13, "quantity" : 120, "quantityFromSimilarOrders" : 265 }
{ "_id" : 4, "type" : "strawberry", "orderDate" : ISODate("2019-05-18T16:09:01Z"),
"state" : "CA", "price" : 41, "quantity" : 162, "quantityFromSimilarOrders" : 162 }
{ "_id" : 3, "type" : "vanilla", "orderDate" : ISODate("2020-02-08T13:13:23Z"),
"state" : "WA", "price" : 13, "quantity" : 104, "quantityFromSimilarOrders" : 244 }
{ "_id" : 1, "type" : "chocolate", "orderDate" : ISODate("2021-03-20T11:30:05Z"),
"state" : "WA", "price" : 14, "quantity" : 140, "quantityFromSimilarOrders" : 244 }
{ "_id" : 5, "type" : "strawberry", "orderDate" : ISODate("2019-01-08T06:12:03Z"),
"state" : "WA", "price" : 43, "quantity" : 134, "quantityFromSimilarOrders" : 134 }Time Range Window Examples时间范围窗口示例
Use a Time Range Window with a Positive Upper Bound使用具有正上限的时间范围窗口
The following example uses a window with a positive upper bound time range unit in 以下示例使用$setWindowFields. The pipeline outputs an array of orderDate values for each state that match the specified time range.$setWindowFields中具有正上限时间范围单位的window。管道输出与指定时间范围匹配的每个state的orderDate值数组。
db.cakeSales.aggregate( [
{
$setWindowFields: {
partitionBy: "$state",
sortBy: { orderDate: 1 },
output: {
recentOrders: {
$push: "$orderDate",
window: {
range: [ "unbounded", 10 ],
unit: "month"
}
}
}
}
}
] )
In the example:在示例中:
partitionBy: "$state"partitions the documents in the collection by按state. There are partitions forCAandWA.state对集合中的文档进行分区。CA和WA有分区。sortBy: { orderDate: 1 }sorts the documents in each partition by按orderDatein ascending order (1), so the earliestorderDateis first.orderDate升序(1)对每个分区中的文档进行排序,因此最早的orderDate位居前列。output:Sets the将recentOrdersfield to an array oforderDatevalues for the documents in eachstate. The array elements are expanded with additions to the previous elements in the array.recentOrders字段设置为每个state的文档的orderDate值数组。数组元素通过添加数组中的前一个元素进行扩展。Uses使用$pushto return an array oforderDatevalues from the documents in a range window.$push从范围窗口中的文档返回orderDate值数组。
The window contains documents between an该unboundedlower limit and an upper limit set to10(10 months after the current document'sorderDatevalue) using a time range unit.window包含使用时间范围单位设置为10(当前文档的orderDate值后10个月)的无限下限和上限之间的文档。$pushreturns the array oforderDatevalues for the documents between the beginning of the partition and the documents withorderDatevalues inclusively in a range of the current document'sorderDatevalue plus10months.$push返回分区开始和orderDate值在当前文档orderDate值加10个月范围内的文档之间的orderDate值数组。
In this example output, the array of 在这个示例输出中,orderDate values for CA and WA is shown in the recentOrders field:CA和WA的orderDate值数组显示在recentOrders字段中:
{ "_id" : 4, "type" : "strawberry", "orderDate" : ISODate("2019-05-18T16:09:01Z"),
"state" : "CA", "price" : 41, "quantity" : 162,
"recentOrders" : [ ISODate("2019-05-18T16:09:01Z") ] }
{ "_id" : 0, "type" : "chocolate", "orderDate" : ISODate("2020-05-18T14:10:30Z"),
"state" : "CA", "price" : 13, "quantity" : 120,
"recentOrders" : [ ISODate("2019-05-18T16:09:01Z"), ISODate("2020-05-18T14:10:30Z"), ISODate("2021-01-11T06:31:15Z") ] }
{ "_id" : 2, "type" : "vanilla", "orderDate" : ISODate("2021-01-11T06:31:15Z"),
"state" : "CA", "price" : 12, "quantity" : 145,
"recentOrders" : [ ISODate("2019-05-18T16:09:01Z"), ISODate("2020-05-18T14:10:30Z"), ISODate("2021-01-11T06:31:15Z") ] }
{ "_id" : 5, "type" : "strawberry", "orderDate" : ISODate("2019-01-08T06:12:03Z"),
"state" : "WA", "price" : 43, "quantity" : 134,
"recentOrders" : [ ISODate("2019-01-08T06:12:03Z") ] }
{ "_id" : 3, "type" : "vanilla", "orderDate" : ISODate("2020-02-08T13:13:23Z"),
"state" : "WA", "price" : 13, "quantity" : 104,
"recentOrders" : [ ISODate("2019-01-08T06:12:03Z"), ISODate("2020-02-08T13:13:23Z") ] }
{ "_id" : 1, "type" : "chocolate", "orderDate" : ISODate("2021-03-20T11:30:05Z"),
"state" : "WA", "price" : 14, "quantity" : 140,
"recentOrders" : [ ISODate("2019-01-08T06:12:03Z"), ISODate("2020-02-08T13:13:23Z"), ISODate("2021-03-20T11:30:05Z") ] }Use a Time Range Window with a Negative Upper Bound使用具有负上限的时间范围窗口
The following example uses a window with a negative upper bound time range unit in 以下示例使用$setWindowFields. $setWindowFields中具有负上限时间范围unit的window。The pipeline outputs an array of 管道输出与指定时间范围匹配的每个orderDate values for each state that match the specified time range.state的orderDate值数组。
db.cakeSales.aggregate( [
{
$setWindowFields: {
partitionBy: "$state",
sortBy: { orderDate: 1 },
output: {
recentOrders: {
$push: "$orderDate",
window: {
range: [ "unbounded", -10 ],
unit: "month"
}
}
}
}
}
] )
In the example:在示例中:
partitionBy: "$state"partitions the documents in the collection by按state. There are partitions forCAandWA.state对集合中的文档进行分区。CA和WA有分区。sortBy: { orderDate: 1 }sorts the documents in each partition by按orderDatein ascending order (1), so the earliestorderDateis first.orderDate升序(1)对每个分区中的文档进行排序,因此最早的orderDate是第一个。output:Sets the将recentOrdersfield to an array oforderDatevalues for the documents in eachstate. The array elements are expanded with additions to the previous elements in the array.recentOrders字段设置为每个state的文档的orderDate值数组。数组元素通过添加数组中的前一个元素进行扩展。Uses使用$pushto return an array oforderDatevalues from the documents in a range window.$push从range窗口中的文档返回orderDate值数组。
The window contains documents between an该unboundedlower limit and an upper limit set to-10(10 months before the current document'sorderDatevalue) using a time range unit.window包含使用时间范围单位设置为-10(当前文档orderDate值前10个月)的unbounded下限和unbounded上限之间的文档。$pushreturns the array oforderDatevalues for the documents between the beginning of the partition and the documents withorderDatevalues inclusively in a range of the current document'sorderDatevalue minus10months.$push返回分区开始和orderDate值在当前文档orderDate值减去10个月范围内的文档之间的orderDate值数组。
In this example output, the array of 在这个示例输出中,orderDate values for CA and WA is shown in the recentOrders field:CA和WA的orderDate值数组显示在recentOrders字段中:
{ "_id" : 4, "type" : "strawberry", "orderDate" : ISODate("2019-05-18T16:09:01Z"),
"state" : "CA", "price" : 41, "quantity" : 162,
"recentOrders" : [ ] }
{ "_id" : 0, "type" : "chocolate", "orderDate" : ISODate("2020-05-18T14:10:30Z"),
"state" : "CA", "price" : 13, "quantity" : 120,
"recentOrders" : [ ISODate("2019-05-18T16:09:01Z") ] }
{ "_id" : 2, "type" : "vanilla", "orderDate" : ISODate("2021-01-11T06:31:15Z"),
"state" : "CA", "price" : 12, "quantity" : 145,
"recentOrders" : [ ISODate("2019-05-18T16:09:01Z") ] }
{ "_id" : 5, "type" : "strawberry", "orderDate" : ISODate("2019-01-08T06:12:03Z"),
"state" : "WA", "price" : 43, "quantity" : 134,
"recentOrders" : [ ] }
{ "_id" : 3, "type" : "vanilla", "orderDate" : ISODate("2020-02-08T13:13:23Z"),
"state" : "WA", "price" : 13, "quantity" : 104,
"recentOrders" : [ ISODate("2019-01-08T06:12:03Z") ] }
{ "_id" : 1, "type" : "chocolate", "orderDate" : ISODate("2021-03-20T11:30:05Z"),
"state" : "WA", "price" : 14, "quantity" : 140,
"recentOrders" : [ ISODate("2019-01-08T06:12:03Z"), ISODate("2020-02-08T13:13:23Z") ] }Comparison with Previous Values Example与先前值的比较示例
The following example uses 以下示例使用$setWindowFields with the $shift operator and the $set stage to compare fields in a collection.$setWindowFields、$shift运算符和$set阶段来比较集合中的字段。
db.cakeSales.aggregate( [
{
$setWindowFields: {
partitionBy: "$type",
sortBy: { orderDate: 1 },
output: {
previousPrice: {
$shift: {
output: "$price",
by: -1
}
}
}
}
},
{
$set: {
priceComparison: {
$cond: [
{ $eq: ["$price", "$previousPrice"] },
"same",
{
$cond: [
{ $gt: ["$price", "$previousPrice"] },
"higher",
"lower"
]
}
]
}
}
},
] )
In the example:在示例中:
partitionBy: "$type"partitions the documents in the collection by按typeso each type's calculations are kept separate.type对集合中的文档进行分区,这样每种类型的计算都是分开的。sortBy: { orderDate: 1 }sorts the documents in each partition by按orderDatein ascending order (1).orderDate升序(1)对每个分区中的文档进行排序。output.previousPriceuses the使用$shiftoperator to capture thepricefrom the immediately preceding order within the same year.$shift运算符捕获同一年内前一个订单的price。$setadds a new field called添加一个名为priceComparison, and sets that field's value tohigher,lower, orsamebased on the comparison topreviousPrice.priceComparison的新字段,并根据与先前价格的比较将该字段的值设置为higher、lower或same。
In this example output, the comparison result is shown in the 在这个示例输出中,比较结果显示在priceComparison field:priceComparison字段中:
[
{
_id: 0,
type: 'chocolate',
orderDate: ISODate('2020-05-18T14:10:30.000Z'),
state: 'CA',
price: 13,
quantity: 120,
previousPrice: null,
priceComparison: 'higher'
},
{
_id: 1,
type: 'chocolate',
orderDate: ISODate('2021-03-20T11:30:05.000Z'),
state: 'WA',
price: 14,
quantity: 140,
previousPrice: 13,
priceComparison: 'higher'
},
{
_id: 5,
type: 'strawberry',
orderDate: ISODate('2019-01-08T06:12:03.000Z'),
state: 'WA',
price: 43,
quantity: 134,
previousPrice: null,
priceComparison: 'higher'
},
{
_id: 4,
type: 'strawberry',
orderDate: ISODate('2019-05-18T16:09:01.000Z'),
state: 'CA',
price: 41,
quantity: 162,
previousPrice: 43,
priceComparison: 'lower'
},
{
_id: 3,
type: 'vanilla',
orderDate: ISODate('2020-02-08T13:13:23.000Z'),
state: 'WA',
price: 13,
quantity: 104,
previousPrice: null,
priceComparison: 'higher'
},
{
_id: 2,
type: 'vanilla',
orderDate: ISODate('2021-01-11T06:31:15.000Z'),
state: 'CA',
price: 12,
quantity: 145,
previousPrice: 13,
priceComparison: 'lower'
}
]C#
The following 以下WeatherMeasurement class represents documents in a collection of weather measurements:WeatherMeasurement类表示天气测量集合中的文档:
public class WeatherMeasurement
{
public Guid Id { get; set; }
public string LocalityId { get; set; }
public DateTime MeasurementDateTime { get; set; }
public float Rainfall { get; set; }
public float Temperature { get; set; }
}
To use the MongoDB .NET/C# driver to add a 要使用MongoDB .NET/C#驱动程序将$setWindowFields stage to an aggregation pipeline, call the SetWindowFields() method on a PipelineDefinition object.$setWindowFields阶段添加到聚合管道中,请在PipelineDefinition对象上调用SetWindowFields()方法。
The following example creates a pipeline stage that uses the 以下示例创建了一个管道阶段,该阶段使用Rainfall and Temperature fields to compute the accumulated rainfall and a moving average temperature over the past month for each locality:Rainfall(降雨)和Temperature(温度)字段计算每个地点过去一个月的累积降雨量和移动平均温度:
var pipeline = new EmptyPipelineDefinition<WeatherMeasurement>()
.SetWindowFields(
partitionBy: w => w.LocalityId,
sortBy: Builders<WeatherMeasurement>.Sort.Ascending(
w => w.MeasurementDateTime),
output: o => new
{
MonthlyRainfall = o.Sum(
w => w.Rainfall, RangeWindow.Create(
RangeWindow.Months(-1),
RangeWindow.Current)
),
TemperatureAvg = o.Average(
w => w.Temperature, RangeWindow.Create(
RangeWindow.Months(-1),
RangeWindow.Current)
)
}
);Node.js
The Node.js examples on this page use the 此页面上的Node.js示例使用Atlas示例数据集中的sample_weatherdata.data collection from the Atlas sample datasets. sample_weatherdata.data集合。To learn how to create a free MongoDB Atlas cluster and load the sample datasets, see Get Started in the MongoDB Node.js driver documentation.要了解如何创建免费的MongoDB Atlas集群并加载示例数据集,请参阅MongoDB Node.js驱动程序文档中的入门。
To use the MongoDB Node.js driver to add a 要使用MongoDB Node.js驱动程序将$setWindowFields stage to an aggregation pipeline, use the $setWindowFields operator in a pipeline object.$setWindowFields阶段添加到聚合管道中,请在管道对象中使用$setWindowFields运算符。
The following example creates a pipeline stage that calculates the average 以下示例创建了一个管道阶段,该阶段计算过去一个月airTemperature.value and the total waveMeasurement.waves.height for each unique value of callLetters over the past month. The example then runs the aggregation pipeline:callLetters的每个唯一值的平均airTemperature.value(空气温度值)和总waveMeasurement.waves.height。然后,该示例运行聚合管道:
const pipeline = [
{
$setWindowFields: {
partitionBy: "$callLetters",
sortBy: { ts: 1 },
output: {
temperatureAvg: {
$avg: "$airTemperature.value",
window: {
range: [-1, "current"],
unit: "month"
}
},
totalWaveHeight: {
$sum: "$waveMeasurement.waves.height",
window: {
range: [-1, "current"],
unit: "month"
}
}
}
}
},
];
const cursor = collection.aggregate(pipeline);
return cursor;Tip
For an additional example about IOT Power Consumption, see the Practical MongoDB Aggregations e-book.有关物联网功耗的更多示例,请参阅实用MongoDB聚合电子书。