Definición
Nuevo en la versión 5.0.
Realiza operaciones en un intervalo específico de documentos en una colección, conocido como ventana, y devuelve los resultados en función de la selección elegida. operador de ventana.
Por ejemplo, se puede utilizar la etapa $setWindowFields para dar salida a la:
Diferencia de ventas entre dos documentos de una colección.
Clasificaciones de ventas.
Totales de ventas acumuladas.
Análisis de información compleja de series de tiempo sin exportar los datos a una base de datos externa.
Sintaxis
La sintaxis de la etapa $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>: { ... } } } }
La etapa $setWindowFields toma un documento con estos campos:
Campo | Necesidad | Descripción |
|---|---|---|
Opcional | Especificar una expresión para agrupar los documentos. En la etapa | |
Requerido para algunos operadores (consultar Restricciones) | Especifica el campo o los campos por los que ordenar los documentos en la partición. Utiliza la misma sintaxis que la etapa | |
Requerido | Especifica el/los campo(s) que se agregarán a los documentos en la salida devuelta por la etapa Un campo puede contener puntos para especificar campos de documentos incrustados y campos de arreglo. La semántica para la notación de puntos del documento incrustado en la etapa
| |
Opcional | Especifica los límites y parámetros de la ventana. Los límites de la ventana son inclusivos. Por defecto, es un período ilimitado, que incluye todos los documentos de la partición. Se debe especificar una ventana de documentos o de rango. | |
Opcional | Una ventana en la que los límites inferior y superior se especifican en relación con la posición del documento actual leído de la colección. Los límites de la ventana se especifican mediante un arreglo de dos elementos que contiene un límite inferior y superior como string o número entero. Uso:
Se pueden consultar ejemplos de ventanas de documentos. | |
Opcional | Una ventana donde los límites inferior y superior se definen mediante un rango de valores basado en el campo sortBy del documento actual. Los límites de la ventana se especifican mediante un arreglo de dos elementos que contiene un string o un número de límite inferior y superior. Uso:
Se puede consultar un ejemplo de ventana de rango. | |
Opcional | Especifica las unidades para los límites de la ventana de tiempo rango. Se puede configurar en una de estas cadenas:
Si se omite, se utilizan los límites de la ventana de rango numérico por defecto. Se pueden consultar ejemplos de ventanas de rango de tiempo. |
Tip
Comportamiento
La etapa $setWindowFields agrega nuevos campos a los documentos existentes. Puedes incluir una o más etapas $setWindowFields en una operación de agregación.
A partir de MongoDB 5.3, puedes usar la etapa $setWindowFields con transacciones y el nivel de consistencia de lectura "snapshot".
La etapa $setWindowFields no garantiza el orden de los documentos devueltos.
Operadores de ventana
Estos operadores se pueden utilizar con la etapa $setWindowFields:
Operadores de acumulación:
$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.
Operadores de relleno de vacíos:
$linearFilly$locf.
Operadores de rango:
$denseRank,$documentNumbery$rank.
Restricciones
Restricciones para la etapa $setWindowFields:
Antes de MongoDB 5.3, la etapa
$setWindowFieldsno puede utilizarse:en transacciones;
con
"snapshot"nivel de consistencia de lectura.
sortBy es necesario para lo siguiente:
Ventanas delimitadas (ya sea una ventana de documentos o una ventana de rango).
$linearFilloperador.
Las ventanas de rango exigen que todos los valores de sortBy sean números.
Las ventanas de rango de tiempo requieren que todos los valores de sortBy sean fechas.
Las ventanas de rango y de rango de tiempo solo pueden contener un campo sortBy y la clasificación debe ser ascendente.
No se puede especificar una ventana de documentos y una ventana de rango a la vez.
Estos operadores utilizan una ventana implícita y devuelven un error si especificas una opción de ventana:
$shiftoperador.
En las ventanas de rango, solo se incluyen en la ventana los números del rango especificado. Se excluyen los valores faltantes, indefinidos y
null.Para ventanas de rango de tiempo:
En la ventana solo se incluyen los tipos de fecha y hora.
Los valores de límite deben ser números enteros. Por ejemplo, puedes usar 2 horas como límite, pero no puedes usar 1,5 horas.
Para ventanas vacías o ventanas con valores incompatibles (por ejemplo, con
$sumen strings), el valor devuelto depende del operador:
Ejemplos
Crea una colección de cakeSales que incluya ventas de pasteles en el estado de California (CA) y Washington (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 } ] )
Los siguientes ejemplos utilizan la colección cakeSales.
Ejemplos de ventanas de documentos
Usa la ventana de documentos para obtener la cantidad acumulada para cada estado
En este ejemplo, se utiliza una ventana de documentos en $setWindowFields para obtener la quantity de las ventas acumuladas de pasteles para cada state:
db.cakeSales.aggregate( [ { $setWindowFields: { partitionBy: "$state", sortBy: { orderDate: 1 }, output: { cumulativeQuantityForState: { $sum: "$quantity", window: { documents: [ "unbounded", "current" ] } } } } } ] )
En el ejemplo:
partitionBy: "$state"particiona los documentos de la colección enstate. Existen particiones paraCAyWA.sortBy: { orderDate: 1 }ordena los documentos de cada partición pororderDateen orden ascendente (1), de modo que elorderDatemás antiguo sea el primero.
output:Establece el campo
cumulativeQuantityForStatealquantityacumulado para cadastate, que aumenta con sumas sucesivas al valor anterior en la partición.Calcula la
quantityacumulativa con el operador$sumque se ejecuta en una ventana de documentos.La ventana contiene documentos entre un límite inferior de
unboundedy el documentocurrent. Esto significa que$sumdevuelve laquantityacumulada para los documentos entre el inicio de la partición y el documento actual.
En este resultado de ejemplo, el quantity acumulativo de CA y WA se muestra en el campo cumulativeQuantityForState:
{ "_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 }
Usa la ventana de documentos para obtener la cantidad acumulada de cada año.
Este ejemplo utiliza una ventana de documentos en $setWindowFields para generar las ventas acumuladas de pasteles quantity para cada $year en orderDate:
db.cakeSales.aggregate( [ { $setWindowFields: { partitionBy: { $year: "$orderDate" }, sortBy: { orderDate: 1 }, output: { cumulativeQuantityForYear: { $sum: "$quantity", window: { documents: [ "unbounded", "current" ] } } } } } ] )
En el ejemplo:
partitionBy: { $year: "$orderDate" }particiona los documentos de la colección por$yearenorderDate. Hay particiones para2019,2020y2021.sortBy: { orderDate: 1 }ordena los documentos de cada partición pororderDateen orden ascendente (1), de modo que elorderDatemás antiguo sea el primero.output:Establece el campo
cumulativeQuantityForYearen laquantityacumulada de cada año, que aumenta con las sucesivas incorporaciones al valor anterior de la partición.Calcula la
quantityacumulativa con el operador$sumque se ejecuta en una ventana de documentos.La ventana contiene documentos entre un límite inferior de
unboundedy el documentocurrent. Esto significa que$sumdevuelve laquantityacumulada para los documentos entre el inicio de la partición y el documento actual.
En este resultado de ejemplo, la quantity acumulativa de cada año se muestra en el campo 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 }
Usa la ventana de documentos para obtener el promedio móvil de cada año.
En este ejemplo, se utiliza una ventana de documentos en $setWindowFields para obtener el promedio móvil de las ventas de pasteles quantity:
db.cakeSales.aggregate( [ { $setWindowFields: { partitionBy: { $year: "$orderDate" }, sortBy: { orderDate: 1 }, output: { averageQuantity: { $avg: "$quantity", window: { documents: [ -1, 0 ] } } } } } ] )
En el ejemplo:
partitionBy: "$orderDate"particiona los documentos de la colección por$yearenorderDate. Hay particiones para2019,2020y2021.sortBy: { orderDate: 1 }ordena los documentos de cada partición pororderDateen orden ascendente (1), de modo que elorderDatemás antiguo sea el primero.output:Establece el campo de
averageQuantityal promedio móvilquantityde cada año.Calcula el promedio móvil
quantityutilizando el operador$avgque se ejecuta en una ventana de documentos.La ventana contiene documentos entre
-1y0. Esto significa que$avgdevuelve el promedia móvilquantityentre el documento anterior al documento actual (-1) y el documento actual (0) en la partición.
En este ejemplo de resultado, el promedio móvil quantity se muestra en el campo 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 }
Utiliza la ventana de documentos para obtener la cantidad acumulada y máxima de cada año
En este ejemplo, se utiliza una ventana de documentos en $setWindowFields para calcular los valores acumulados y máximos de ventas de pasteles quantity de cada $year en orderDate:
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" ] } } } } } ] )
En el ejemplo:
partitionBy: "$orderDate"particiona los documentos de la colección por$yearenorderDate. Hay particiones para2019,2020y2021.sortBy: { orderDate: 1 }ordena los documentos de cada partición pororderDateen orden ascendente (1), de modo que elorderDatemás antiguo sea el primero.output:Establece el campo
cumulativeQuantityForYearen laquantityacumulada de cada año.Calcula la
quantityacumulativa con el operador$sumque se ejecuta en una ventana de documentos.La ventana contiene documentos entre un límite inferior de
unboundedy el documentocurrent. Esto significa que$sumdevuelve la cantidad acumulada para los documentos entre el inicio de la partición y el documento actual.Establece el campo
maximumQuantityForYearen el máximo dequantitypara cada año.Calcula la
quantitymáxima de todos los documentos con el operador$maxque se ejecuta en una ventana de documentos.La ventana contiene documentos entre un límite inferior de
unboundedyupper. Esto significa que$maxdevuelve la cantidad máxima de documentos en la partición.
En este ejemplo de resultado, la quantity acumulada se muestra en el campo cumulativeQuantityForYear y la quantity máxima se muestra en el campo 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 }
Ejemplo de ventana de rango
Este ejemplo utiliza una ventana de rango en $setWindowFields para devolver la suma de los valores quantity de pasteles vendidos para pedidos dentro de más o menos 10 dólares del valor price del documento actual:
db.cakeSales.aggregate( [ { $setWindowFields: { partitionBy: "$state", sortBy: { price: 1 }, output: { quantityFromSimilarOrders: { $sum: "$quantity", window: { range: [ -10, 10 ] } } } } } ] )
En el ejemplo:
partitionBy: "$state"particiona los documentos de la colección enstate. Existen particiones paraCAyWA.sortBy: { price: 1 }ordena los documentos de cada partición porpriceen orden ascendente (1), de modo que elpricemás bajo sea el primero.outputestablece el campoquantityFromSimilarOrdersen la suma de los valoresquantityde los documentos de una ventana de rango.
En este ejemplo de resultado, la suma de los valores de quantity de los documentos en la ventana se muestra en el campo 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 }
Ejemplos de ventanas de rango de tiempo
Utiliza una ventana de rango de tiempo con un límite superior positivo.
En el siguiente ejemplo, se utiliza una ventana con una unidad de rango de tiempo de límite superior positivo en $setWindowFields. El pipeline genera un arreglo de valores orderDate para cada state que coincide con el rango de tiempo especificado.
db.cakeSales.aggregate( [ { $setWindowFields: { partitionBy: "$state", sortBy: { orderDate: 1 }, output: { recentOrders: { $push: "$orderDate", window: { range: [ "unbounded", 10 ], unit: "month" } } } } } ] )
En el ejemplo:
partitionBy: "$state"particiona los documentos de la colección enstate. Existen particiones paraCAyWA.sortBy: { orderDate: 1 }ordena los documentos de cada partición pororderDateen orden ascendente (1), de modo que elorderDatemás antiguo sea el primero.output:
La ventana contiene documentos entre un límite inferior de
unboundedy un límite superior establecido en10(10 meses después del valororderDatedel documento actual) y utiliza una unidad de rango de tiempo.$pushdevuelve el arreglo de valoresorderDatepara los documentos entre el principio de la partición y los documentos con valoresorderDateinclusive en un rango del valororderDatedel documento actual más10meses.
En este resultado de ejemplo, el arreglo de valores orderDate para CA y WA se muestra en el campo 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") ] }
Utiliza una ventana de rango temporal con un límite superior negativo.
El siguiente ejemplo utiliza una ventana con una unidad de rango de tiempo de límite superior negativo en $setWindowFields. El pipeline genera un arreglo de valores orderDate para cada state que coincide con el rango de tiempo especificado.
db.cakeSales.aggregate( [ { $setWindowFields: { partitionBy: "$state", sortBy: { orderDate: 1 }, output: { recentOrders: { $push: "$orderDate", window: { range: [ "unbounded", -10 ], unit: "month" } } } } } ] )
En el ejemplo:
partitionBy: "$state"particiona los documentos de la colección enstate. Existen particiones paraCAyWA.sortBy: { orderDate: 1 }ordena los documentos de cada partición pororderDateen orden ascendente (1), de modo que elorderDatemás antiguo sea el primero.output:
La ventana contiene documentos entre un límite inferior de
unboundedy un límite superior establecido en-10(10 meses antes del valororderDatedel documento actual) con una unidad de rango de tiempo.$pushdevuelve el arreglo de valoresorderDatepara los documentos entre el principio de la partición y los documentos con valoresorderDateinclusive dentro de un rango del valororderDatedel documento actual menos10meses.
En este resultado de ejemplo, el arreglo de valores orderDate para CA y WA se muestra en el campo 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") ] }
Ejemplo de comparación con valores anteriores
El siguiente ejemplo utiliza $setWindowFields con el operador $shift y la etapa $set para comparar campos en una colección.
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" ] } ] } } }, ] )
En el ejemplo:
partitionBy: "$type"particiona los documentos en la colección portypepara que los cálculos de cada tipo se mantengan separados.sortBy: { orderDate: 1 }ordena los documentos de cada partición pororderDateen orden ascendente (1).output.previousPriceutiliza el operador$shiftpara capturar elpricedel orden inmediato anterior dentro del mismo año.$setañade un nuevo campo denominadopriceComparisony establece el valor de ese campo enhigher,lowerosameen función de la comparación conpreviousPrice.
En este resultado de ejemplo, el resultado de la comparación se muestra en el campo 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' } ]
La siguiente clase WeatherMeasurement representa documentos de una colección de mediciones meteorológicas:
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; } }
Para usar el controlador MongoDB.NET/C# para agregar una $setWindowFields etapa a una canalización de agregación, llame a SetWindowFields()método en un PipelineDefinition objeto.
En el siguiente ejemplo, se crea una etapa de pipeline que utiliza los campos Rainfall y Temperature para calcular la precipitación acumulada, la temperatura promedio móvil, la temperatura mediana y la precipitación del percentil 90 durante el último mes para cada localidad:
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) ), MedianTemperature = o.Median( w => w.Temperature, RangeWindow.Create( RangeWindow.Months(-1), RangeWindow.Current) ), NinetiethPercentileRainfall = o.Percentile( w => w.Rainfall, new[] { 0.9 }, RangeWindow.Create( RangeWindow.Months(-1), RangeWindow.Current) ) } );
Los ejemplos de Node.js en esta página utilizan la colección sample_weatherdata.data de los conjuntos de datos de muestra de Atlas. Para aprender a crear un clúster gratuito de MongoDB Atlas y cargar los conjuntos de datos de muestra, se puede consultar Primeros pasos en la documentación del driver de MongoDB Node.js.
Para utilizar el controlador de MongoDB Node.js para agregar una etapa de $setWindowFields a una canalización de agregación, utilice el Operador $setWindowFields en un objeto de canalización.
El siguiente ejemplo crea una etapa del pipeline que calcula el airTemperature.value promedio y el waveMeasurement.waves.height total para cada valor único de callLetters durante el último mes. A continuación, el ejemplo ejecuta el pipeline de agregación:
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
Para un ejemplo adicional sobre Consumo de energía de IoT, consulte el libro electrónico Agregaciones prácticas de MongoDB.