Definición
$fillNovedades en la versión 5.3.
Rellena
nully los valores de campo faltantes dentro de los documentos.Puede usar
$fillpara rellenar los puntos de datos faltantes:En una secuencia basada en valores circundantes.
Con un valor fijo.
Sintaxis
La etapa $fill tiene esta 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 Si omites partitionBy y partitionByFields, partitionBy y partitionByFields son mutuamente excluyentes. Ve un ejemplo. | |
Opcional | Especifica un arreglo de campos como clave compuesta para agrupar los documentos. En la Si omites partitionBy y partitionByFields, partitionBy y partitionByFields son mutuamente excluyentes. | |
Obligatorio si method se especifica en al menos una output.<field>. De lo contrario, opcional. | Especifica el campo o campos para ordenar los documentos dentro de cada partición. Utiliza la misma sintaxis que la etapa | |
Requerido | Especifica un objeto que contiene cada campo para el cual se deben completar los valores faltantes. Puedes especificar varios campos en el objeto de salida. El nombre del objeto es el nombre del campo que se debe completar. El valor del objeto especifica cómo se llena el campo. | |
Requerido | Especifica un objeto que indica cómo rellenar los valores ausentes en el campo objetivo. El nombre del objeto debe ser
|
Comportamiento y restricciones
partitionByFields Restricciones
$fill devuelve un error si cualquier nombre de campo en el arreglo partitionByFields:
Evalúa a un valor que no es una cadena.
Comienza con
$.
linear Comportamiento
El método fill linear llena null y los campos faltantes usando interpolación lineal basándose en los valores circundantes nonull en la secuencia.
Para cada documento donde el campo es
nullo falta,linearFillllena esos campos en proporción al rango de valores faltantes entre los valores circundantes que no sonnullde acuerdo con el orden de sortBy. Para determinar los valores de los campos que faltan,linearFillusa:La diferencia de los valores no
nullcircundantes.El número de campos
nulla llenar 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 usar el método de llenado
linearpara llenar los valoresnull, los documentos se vuelven:{ 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 que no sonnullpermanecennull.Para utilizar el método de completado
linear, también debes utilizar el campo sortBy para ordenar tus datos.
Para ver un ejemplo completo utilizando el método de llenado linear, consulta Completa los valores de los campos faltantes con interpolación lineal.
locf Comportamiento
locf corresponde a la última observación trasladada.
Si un campo que se está llenando contiene tanto
nullcomo valores no nulos,locfestablece los valoresnully los valores faltantes en el último valor no nulo conocido del campo según el orden sortBy.Si el campo contiene solo
nullo valores faltantes en una partición,locfestablece el valor del campo ennullpara esa partición.nully los campos faltantes que aparecen antes de los valores no nulos en el orden de clasificación permanecennull.
Para utilizar el método de completado
locf, también debes utilizar el campo sortBy para ordenar tus datos.
Para un ejemplo completo utilizando el método de llenado locf, consulte Completa los Valores Faltantes de campos Basados en el Último Valor Observado.
Comparación de operadores de $fill y agregación
Para completar null y los valores de campos faltantes dentro de un documento puedes usar:
La etapa de
$fill.Cuando utilizas la etapa
$fill, el campo que especificas en la salida es el mismo campo que se utiliza como fuente de datos.Los operadores de agregación
$linearFilly$locf.Cuando
$linearFillo$locf, pueden establecerse valores para un campo diferente del que se utiliza como datos fuente.
Ejemplos
Los ejemplos de esta sección muestran cómo usar $fill para completar los valores faltantes:
Completar valores de campos faltantes con un valor constante
Una tienda de calzado mantiene una colección dailySales que contiene un documento que resume las ventas diarias. La tienda de zapatos 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 $fill para establecer las cantidades vendidas en 0 para los tipos de calzado faltantes en las ventas de cada día:
db.dailySales.aggregate( [ { $fill: { output: { "bootsSold": { value: 0 }, "sandalsSold": { value: 0 }, "sneakersSold": { value: 0 } } } } ] )
En el pipeline anterior:
$fillrellena los valores para los campos que faltan.output especifica:
Los nombres de los campos a completar.
- El valor para establecer en los campos completados. En este ejemplo, el
- 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 valores de campos 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 en algunos de los documentos de la colección.
Para rellenar los valores faltantes de price usando interpolación lineal, utiliza $fill con el método de relleno linear:
db.stock.aggregate( [ { $fill: { sortBy: { time: 1 }, output: { "price": { method: "linear" } } } } ] )
En el pipeline anterior:
$fillrellena los valores para los campos que faltan.sortBy: { time: 1 }ordena los documentos por el campotimeen orden ascendente, de más antiguo a más reciente.output especifica:
pricecomo el campo para completar los valores faltantes.{ method: "linear" }como el método de llenado. El rellenolinear- el método completa los valores de
priceque faltan utilizando interpolación lineal según los valores circundantes depriceen 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 } ]
Rellenar 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 en algunos de los documentos de la colección.
Para completar los campos score faltantes y garantizar que no haya vacíos en los datos, utiliza $fill. En el siguiente ejemplo, $fill utiliza el método de llenado locf para completar los valores faltantes de score con el score anterior en la secuencia:
db.restaurantReviews.aggregate( [ { $fill: { sortBy: { date: 1 }, output: { "score": { method: "locf" } } } } ] )
En el pipeline anterior:
$fillcompleta los valores descoreque faltan.sortBy: { date: 1 }ordena los documentos por el campodateen orden ascendente, de más antiguo a más reciente.output especifica:
scorecomo el campo para completar los valores faltantes.{ method: "locf" }como el método de llenado. El rellenolocf- el método rellena los valores perdidos de
scorecon 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 } ]
Rellene datos para particiones distintas
Considera el ejemplo anterior con revisiones de restaurantes, pero en lugar de hacer el seguimiento de un solo restaurante, la colección ahora contiene revisiones de múltiples restaurantes.
Cree una colección llamada restaurantReviewsMultiple y llene la colección 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 en algunos de los documentos de la colección.
Para completar los campos score faltantes y garantizar que no haya vacíos en los datos, utiliza $fill. En el siguiente ejemplo, $fill utiliza el método de llenado locf para completar los valores faltantes de score con el score anterior en la secuencia:
db.restaurantReviewsMultiple.aggregate( [ { $fill: { sortBy: { date: 1 }, partitionBy: { "restaurant": "$restaurant" }, output: { "score": { method: "locf" } } } } ] )
En el pipeline anterior:
$fillcompleta los valores descoreque faltan.sortBy: { date: 1 }ordena los documentos por el campodateen orden ascendente, de más antiguo a más reciente.partitionBy: { "restaurant": "$restaurant" }divide los datos porrestaurant. Hay dos restaurantes:Joe's PizzaySally's Deli.output especifica:
scorecomo el campo para completar los valores faltantes.{ method: "locf" }como el método de llenado. El rellenolocf- el método rellena los valores perdidos de
scorecon 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 } ]
Indica si un campo se rellenó 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 las puntuaciones de revisión 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") } ] )
El campo score falta en algunos de los documentos de la colección. Puede rellenar los valores faltantes de score utilizando el operador $fill.
Crear una pipeline para realizar las siguientes acciones:
Usa
$setpara añadir un nuevo campo a cada documento que indique si el camposcoredel documento existe antes de que el operador$fillllene los valores. Este nuevo campo se llamavalueExisted.Rellenar los valores faltantes de
scorecon el últimoscoreobservado en la secuencia. El método filllocfrepresenta "última observación cargada".
La pipeline se asemeja al siguiente código:
db.restaurantReviews.aggregate( [ { $set: { "valueExisted": { "$ifNull": [ { "$toBool": { "$toString": "$score" } }, false ] } } }, { $fill: { sortBy: { date: 1 }, output: { "score": { method: "locf" } } } } ] )
Nota
Gestión 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 } ]
Interpolar los Mismos Valores en Diferentes Particiones
Cambiado en la versión 8.0.
A partir de MongoDB 8.0, $fill puede utilizar el método linear para interpolar si hay valores idénticos en diferentes particiones.
Cree la siguiente colección de restaurantReviewsMultiple que contiene los siguientes documentos, los cuales almacenan puntuaciones de reseñas de restaurantes en fechas idénticas:
db.restaurantReviewsMultiple.insertMany( [ { date: ISODate("2021-03-08"), restaurant: "Steve's Pizza", score: 90 }, { date: ISODate("2021-03-08"), restaurant: "Sally's Deli", score: 75 } ] )
El siguiente ejemplo de agregación usa "linear" para interpolar las fechas idénticas en las diferentes particiones:
db.restaurantReviewsMultiple.aggregate( [ { $fill: { sortBy: { date: 1 }, partitionBy: { "restaurant": "$restaurant" }, output: { "score": { method: "linear" } } } } ] )
A partir de MongoDB 8.1, el ejemplo devuelve el siguiente output:
[ { _id: ObjectId("620559f4394d47411658b590"), date: ISODate("2021-03-08T00:00:00.000Z"), restaurant: "Sally's Deli", score: 75 }, { _id: ObjectId("620559f4394d47411658b58f"), date: ISODate("2021-03-08T00:00:00.000Z"), restaurant: "Steve's Pizza", score: 90 } ]
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 pipeline que rellena valores nulos o faltantes. El pipeline incluye las siguientes etapas:
La etapa
$groupagrupa los documentos de entrada según su campotsy calcula el promedio deseaSurfaceTemperature.valuepara cada grupo.La etapa
$fillordena los datos agrupados por el campo_iden orden ascendente y rellena con valores nulos o faltantes deseaSurfaceTemperatureal usar la 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;