Definición
$fillNovedades en la versión 5.3.
Rellena
nully los valores de campo faltantes dentro de los documentos.Puede utilizar para completar los puntos de datos
$fillfaltantes:En una secuencia basada en valores circundantes.
Con un valor fijo.
Sintaxis
La etapa tiene esta $fill sintaxis:
{ $fill: { partitionBy: <expression>, partitionByFields: [ <field 1>, <field 2>, ... , <field n> ], sortBy: { <sort field 1>: <sort order>, <sort field 2>: <sort order>, ..., <sort field n>: <sort order> }, output: { <field 1>: { value: <expression> }, <field 2>: { method: <string> }, ... } } }
La etapa $fill toma un documento con estos campos:
Campo | Necesidad | Descripción |
|---|---|---|
Opcional | Especifica una expresión para agrupar los documentos. En la etapa, un grupo Si omite partitionBy y partitionByFields, partitionBy y partitionByFields son mutuamente excluyentes. Vea un ejemplo. | |
Opcional | Especifica una matriz de campos como clave compuesta para agrupar los documentos. En la etapa, cada grupo Si omite partitionBy y partitionByFields, partitionBy y partitionByFields son mutuamente excluyentes. | |
Obligatorio si el método se especifica en al menos una salida..<field> De lo contrario, opcional. | Especifica el campo o los campos para ordenar los documentos dentro de cada partición. Utiliza la misma sintaxis que la | |
Requerido | ||
Requerido | Especifica un objeto que indica cómo completar los valores faltantes en el campo de destino. El nombre del objeto debe ser
|
Comportamiento y restricciones
partitionByFields Restricciones
$fill devuelve un error si hay algún nombre de campo en la matriz partitionByFields:
Se evalúa como un valor que no es una cadena.
Comienza con
$.
linear Comportamiento
El linear método de relleno rellena null los campos y faltantes mediante interpolación lineal basada en los valores circundantes nonull en la secuencia.
Para cada documento donde el campo es
nullo falta,linearFillrellena esos campos proporcionalmente al rango de valores faltantesnullentre los valores circundantes que no son, según el orden sortBy. Para determinar los valores de los campos faltantes,linearFillutiliza:La diferencia de los valores no
nullcircundantes.El número de
nullcampos a rellenar entre los valores circundantes.
El método
linearpuede rellenar múltiples valores consecutivos denullsi dichos valores están precedidos y seguidos por valores que no seannull, de acuerdo con el orden sortBy.Ejemplo
Si una colección contiene estos documentos:
{ index: 0, value: 0 }, { index: 1, value: null }, { index: 2, value: null }, { index: 3, value: null }, { index: 4, value: 10 } Después de utilizar el método de relleno
linearpara completar los valoresnull, los documentos se convierten en:{ index: 0, value: 0 }, { index: 1, value: 2.5 }, { index: 2, value: 5 }, { index: 3, value: 7.5 }, { index: 4, value: 10 } nullLos valores que no están precedidos ni seguidos por valores distintos denullsiguen siendonull.Para utilizar el método de completado
linear, también debes utilizar el campo sortBy para ordenar tus datos.Al utilizar el
linearmétodo de relleno, devuelve un error si$fillhay valores repetidos en el campo sortBy en una sola partición.
Para ver un ejemplo completo que utiliza el linear método de relleno, consulte Rellenar valores de campo faltantes con interpolación lineal.
locf Comportamiento
locf corresponde a la última observación trasladada.
Si un campo que se está completando contiene
nullvalores y no nulos,locfestablece losnullvalores y faltantes en el último valor no nulo conocido del campo según el orden sortBy.Para utilizar el método de completado
locf, también debes utilizar el campo sortBy para ordenar tus datos.
Para ver un ejemplo completo que utiliza el locf método de relleno, consulte Rellenar valores de campo faltantes según el último valor observado.
Comparación de $fill los operadores y de agregación
Para completar null y los valores de campos faltantes dentro de un documento puedes usar:
La
$filletapa.Cuando utiliza la etapa, el campo que especifica en la salida es el mismo campo utilizado como datos de
$fillorigen.Los operadores de agregación
$linearFill$locfy.Cuando usa o, puede establecer valores para un campo diferente del campo utilizado como datos de
$linearFill$locforigen.
Ejemplos
Los ejemplos de esta sección muestran cómo utilizar para completar valores $fill faltantes:
Complete los valores de campo faltantes con un valor constante
Una zapatería mantiene una colección dailySales que contiene un documento que resume las ventas diarias. La zapatería vende estos tipos de zapatos:
bootssandalssneakers
Cree la siguiente colección dailySales:
db.dailySales.insertMany( [ { "date": ISODate("2022-02-02"), "bootsSold": 10, "sandalsSold": 20, "sneakersSold": 12 }, { "date": ISODate("2022-02-03"), "bootsSold": 7, "sneakersSold": 18 }, { "date": ISODate("2022-02-04"), "sneakersSold": 5 } ] )
No todos los documentos en la colección dailySales contienen cada tipo de zapato. Si falta un tipo de zapato, significa que no se vendieron zapatos de ese tipo en la fecha correspondiente.
El siguiente ejemplo utiliza para establecer las cantidades vendidas $fill en 0 para los tipos de zapatos faltantes para las ventas de cada día:
db.dailySales.aggregate( [ { $fill: { output: { "bootsSold": { value: 0 }, "sandalsSold": { value: 0 }, "sneakersSold": { value: 0 } } } } ] )
En el pipeline anterior:
$fillCompleta los valores de los campos faltantes.La salida especifica:
Los nombres de los campos a rellenar.
- El valor que se debe establecer en los campos rellenados. En este ejemplo,
- La salida especifica un valor constante de
0.
Ejemplo de salida:
[ { _id: ObjectId("6202df9f394d47411658b51e"), date: ISODate("2022-02-02T00:00:00.000Z"), bootsSold: 10, sandalsSold: 20, sneakersSold: 12 }, { _id: ObjectId("6202df9f394d47411658b51f"), date: ISODate("2022-02-03T00:00:00.000Z"), bootsSold: 7, sneakersSold: 18, sandalsSold: 0 }, { _id: ObjectId("6202df9f394d47411658b520"), date: ISODate("2022-02-04T00:00:00.000Z"), sneakersSold: 5, bootsSold: 0, sandalsSold: 0 } ]
Rellenar los valores de campo faltantes con interpolación lineal
Cree una colección stock que contenga los siguientes documentos, que rastrean el precio de las acciones de una sola empresa en intervalos de una hora:
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 } ] )
Falta el campo price para algunos de los documentos de la colección.
Para completar los price valores faltantes mediante interpolación lineal, utilice con $fill el linear método de relleno:
db.stock.aggregate( [ { $fill: { sortBy: { time: 1 }, output: { "price": { method: "linear" } } } } ] )
En el pipeline anterior:
$fillCompleta los valores de los campos faltantes.sortBy: { time: 1 }ordena los documentos por el campotimeen orden ascendente, del más antiguo al más reciente.La salida especifica:
pricecomo el campo en el que se deben rellenar los valores faltantes.{ method: "linear" }como método de relleno. El rellenolinear- El método completa
pricelos valores faltantes mediante interpolación lineal basada en lospricevalores circundantes en la secuencia.
Ejemplo de salida:
[ { _id: ObjectId("620ad41c394d47411658b5e9"), time: ISODate("2021-03-08T09:00:00.000Z"), price: 500 }, { _id: ObjectId("620ad41c394d47411658b5ea"), time: ISODate("2021-03-08T10:00:00.000Z"), price: 507.5 }, { _id: ObjectId("620ad41c394d47411658b5eb"), time: ISODate("2021-03-08T11:00:00.000Z"), price: 515 }, { _id: ObjectId("620ad41c394d47411658b5ec"), time: ISODate("2021-03-08T12:00:00.000Z"), price: 505 }, { _id: ObjectId("620ad41c394d47411658b5ed"), time: ISODate("2021-03-08T13:00:00.000Z"), price: 495 }, { _id: ObjectId("620ad41c394d47411658b5ee"), time: ISODate("2021-03-08T14:00:00.000Z"), price: 485 } ]
Completar los valores de campo faltantes según el último valor observado
Cree una colección restaurantReviews que contenga los siguientes documentos, que almacenan puntuaciones de reseñas de un solo restaurante a lo largo del tiempo:
db.restaurantReviews.insertMany( [ { date: ISODate("2021-03-08"), score: 90 }, { date: ISODate("2021-03-09"), score: 92 }, { date: ISODate("2021-03-10") }, { date: ISODate("2021-03-11") }, { date: ISODate("2021-03-12"), score: 85 }, { date: ISODate("2021-03-13") } ] )
Falta el campo score para algunos de los documentos de la colección.
Para rellenar los campos score faltantes y garantizar que no haya espacios en blanco en los datos, utilice$fill. En el siguiente ejemplo, $fillutiliza el método de relleno locf para rellenar los valores score faltantes con los valores score anteriores de la secuencia:
db.restaurantReviews.aggregate( [ { $fill: { sortBy: { date: 1 }, output: { "score": { method: "locf" } } } } ] )
En el pipeline anterior:
$fillcompleta losscorevalores faltantes.sortBy: { date: 1 }ordena los documentos por el campodateen orden ascendente, del más antiguo al más reciente.La salida especifica:
scorecomo el campo en el que se deben rellenar los valores faltantes.{ method: "locf" }como método de relleno. El rellenolocf- El método rellena los valores
scorefaltantes con el últimoscoreobservado en la secuencia.
Ejemplo de salida:
[ { _id: ObjectId("62040bc9394d47411658b553"), date: ISODate("2021-03-08T00:00:00.000Z"), score: 90 }, { _id: ObjectId("62040bc9394d47411658b554"), date: ISODate("2021-03-09T00:00:00.000Z"), score: 92 }, { _id: ObjectId("62040bc9394d47411658b555"), date: ISODate("2021-03-10T00:00:00.000Z"), score: 92 }, { _id: ObjectId("62040bc9394d47411658b556"), date: ISODate("2021-03-11T00:00:00.000Z"), score: 92 }, { _id: ObjectId("62040bc9394d47411658b557"), date: ISODate("2021-03-12T00:00:00.000Z"), score: 85 }, { _id: ObjectId("62040bc9394d47411658b558"), date: ISODate("2021-03-13T00:00:00.000Z"), score: 85 } ]
Rellenar datos para particiones distintas
Considere el ejemplo anterior con reseñas de restaurantes, pero en lugar de rastrear un solo restaurante, la colección ahora contiene reseñas de varios restaurantes.
Cree una colección llamada restaurantReviewsMultiple y complétela con estos documentos:
db.restaurantReviewsMultiple.insertMany( [ { date: ISODate("2021-03-08"), restaurant: "Joe's Pizza", score: 90 }, { date: ISODate("2021-03-08"), restaurant: "Sally's Deli", score: 75 }, { date: ISODate("2021-03-09"), restaurant: "Joe's Pizza", score: 92 }, { date: ISODate("2021-03-09"), restaurant: "Sally's Deli" }, { date: ISODate("2021-03-10"), restaurant: "Joe's Pizza" }, { date: ISODate("2021-03-10"), restaurant: "Sally's Deli", score: 68 }, { date: ISODate("2021-03-11"), restaurant: "Joe's Pizza", score: 93 }, { date: ISODate("2021-03-11"), restaurant: "Sally's Deli" } ] )
Falta el campo score para algunos de los documentos de la colección.
Para rellenar los campos score faltantes y garantizar que no haya espacios en blanco en los datos, utilice$fill. En el siguiente ejemplo, $fillutiliza el método de relleno locf para rellenar los valores score faltantes con los valores score anteriores de la secuencia:
db.restaurantReviewsMultiple.aggregate( [ { $fill: { sortBy: { date: 1 }, partitionBy: { "restaurant": "$restaurant" }, output: { "score": { method: "locf" } } } } ] )
En el pipeline anterior:
$fillcompleta losscorevalores faltantes.sortBy: { date: 1 }ordena los documentos por el campodateen orden ascendente, del más antiguo al más reciente.partitionBy: { "restaurant": "$restaurant" }Divide los datos porrestaurant. Hay dos restaurantes:Joe's PizzaySally's Deli.La salida especifica:
scorecomo el campo en el que se deben rellenar los valores faltantes.{ method: "locf" }como método de relleno. El rellenolocf- El método rellena los valores
scorefaltantes con el últimoscoreobservado en la secuencia.
Ejemplo de salida:
[ { _id: ObjectId("620559f4394d47411658b58f"), date: ISODate("2021-03-08T00:00:00.000Z"), restaurant: "Joe's Pizza", score: 90 }, { _id: ObjectId("620559f4394d47411658b591"), date: ISODate("2021-03-09T00:00:00.000Z"), restaurant: "Joe's Pizza", score: 92 }, { _id: ObjectId("620559f4394d47411658b593"), date: ISODate("2021-03-10T00:00:00.000Z"), restaurant: "Joe's Pizza", score: 92 }, { _id: ObjectId("620559f4394d47411658b595"), date: ISODate("2021-03-11T00:00:00.000Z"), restaurant: "Joe's Pizza", score: 93 }, { _id: ObjectId("620559f4394d47411658b590"), date: ISODate("2021-03-08T00:00:00.000Z"), restaurant: "Sally's Deli", score: 75 }, { _id: ObjectId("620559f4394d47411658b592"), date: ISODate("2021-03-09T00:00:00.000Z"), restaurant: "Sally's Deli", score: 75 }, { _id: ObjectId("620559f4394d47411658b594"), date: ISODate("2021-03-10T00:00:00.000Z"), restaurant: "Sally's Deli", score: 68 }, { _id: ObjectId("620559f4394d47411658b596"), date: ISODate("2021-03-11T00:00:00.000Z"), restaurant: "Sally's Deli", score: 68 } ]
Indique si un campo se completó utilizando $fill
Cuando se completan valores faltantes, la salida no indica si un valor fue completado con el operador $fill o si el valor existía originalmente en el documento. Para distinguir entre valores completados y preexistentes, puedes usar una etapa $set antes de $fill y establecer un nuevo campo en función de si el valor existe.
Por ejemplo, cree una colección restaurantReviews que contenga los siguientes documentos, que almacenan puntuaciones de reseñas de un restaurante a lo largo del tiempo:
db.restaurantReviews.insertMany( [ { date: ISODate("2021-03-08"), score: 90 }, { date: ISODate("2021-03-09"), score: 92 }, { date: ISODate("2021-03-10") }, { date: ISODate("2021-03-11") }, { date: ISODate("2021-03-12"), score: 85 }, { date: ISODate("2021-03-13") } ] )
Falta el campo score en algunos documentos de la colección. Puede completar los valores score faltantes con el operador $fill.
Cree una canalización para realizar las siguientes acciones:
Utilice para añadir un nuevo campo a cada documento que indique si el campo del
$setdocumentoscoreexistía antes de que el$filloperador rellenara los valores. Este nuevo campo sevalueExistedllama.Rellene los valores faltantes
scorecon la última observaciónscorede la secuencia. El método de rellenolocfsignifica "última observación transferida".
La tubería se parece al siguiente código:
db.restaurantReviews.aggregate( [ { $set: { "valueExisted": { "$ifNull": [ { "$toBool": { "$toString": "$score" } }, false ] } } }, { $fill: { sortBy: { date: 1 }, output: { "score": { method: "locf" } } } } ] )
Nota
Manejo de valores de cero
Salida:
[ { _id: ObjectId("63595116b1fac2ee2e957f15"), date: ISODate("2021-03-08T00:00:00.000Z"), score: 90, valueExisted: true }, { _id: ObjectId("63595116b1fac2ee2e957f16"), date: ISODate("2021-03-09T00:00:00.000Z"), score: 92, valueExisted: true }, { _id: ObjectId("63595116b1fac2ee2e957f17"), date: ISODate("2021-03-10T00:00:00.000Z"), valueExisted: false, score: 92 }, { _id: ObjectId("63595116b1fac2ee2e957f18"), date: ISODate("2021-03-11T00:00:00.000Z"), valueExisted: false, score: 92 }, { _id: ObjectId("63595116b1fac2ee2e957f19"), date: ISODate("2021-03-12T00:00:00.000Z"), score: 85, valueExisted: true }, { _id: ObjectId("63595116b1fac2ee2e957f1a"), date: ISODate("2021-03-13T00:00:00.000Z"), valueExisted: false, score: 85 } ]
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 $fill a una canalización de agregación, utilice el Operador $fill en un objeto de canalización.
El siguiente ejemplo crea una canalización que completa valores nulos o faltantes. La canalización incluye las siguientes etapas:
La etapa agrupa los documentos de entrada por
$groupsutscampo y calcula el promedio de cadaseaSurfaceTemperature.valuegrupo.La etapa ordena los datos agrupados por
$fillel_idcampo en orden ascendente y completa losseaSurfaceTemperaturevalores nulos o faltantes mediante interpolación lineal.
const pipeline = [ { $group: { _id: "$ts", seaSurfaceTemperature: { $avg: "$seaSurfaceTemperature.value" }, } }, { $fill: { sortBy: { _id: 1 }, output: { seaSurfaceTemperature: { method: "linear" } } } } ]; const cursor = collection.aggregate(pipeline); return cursor;