Definição
$fillNovidades na versão 5.3.
Preenche
nulle os valores de campo ausentes nos documentos.You can use
$fillto populate missing data points:Em uma sequência baseada em valores circundantes.
Com um valor fixo.
Sintaxe
The $fill stage has this syntax:
{ $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> }, ... } } }
The $fill stage takes a document with these fields:
Campo | necessidade | Descrição |
|---|---|---|
Opcional | Specifies an expression to group the documents. In the If you omit partitionBy and partitionByFields, partitionBy and partitionByFields are mutually exclusive. Veja um exemplo. | |
Opcional | Specifies an array of fields as the compound key to group the documents. In the If you omit partitionBy and partitionByFields, partitionBy and partitionByFields are mutually exclusive. | |
Required if method is specified in at least one output.<field>. Caso contrário, opcional. | Especifica o campo ou campos para classificar os documentos dentro de cada partição. Utiliza a mesma sintaxe que o estágio | |
Obrigatório | Especifica um objeto contendo cada campo para o qual preencher os valores ausentes. Você pode especificar vários campos no objeto saída. O nome do objeto é o nome do campo a ser preenchido. O valor do objeto especifica como o campo é preenchido. | |
Obrigatório | Especifica um objeto indicando como preencher valores ausentes no campo de destino. O nome do objeto deve ser
|
Comportamento e restrições
partitionByFields Restrições
$fill returns an error if any field name in the partitionByFields array:
Avalia para um valor não string.
Começa com
$.
linear Comportamento
O método de preenchimento linear preenche campos null e ausentes usando interpolação linear com base nos valores não-null circundantes na sequência.
For each document where the field is
nullor missing,linearFillfills those fields in proportion to the missing value range between surrounding non-nullvalues according to the sortBy order. To determine the values for missing fields,linearFilluses:A diferença entre os valores circundantes que não são
null.O número de
nullcampos para preencher entre os valores circundantes.
O método
linearpode preencher vários valores denullconsecutivos se esses valores forem precedidos e seguidos por valores nãonullde acordo com a ordem sortBy .Exemplo
Se uma coleção contiver estes documentos:
{ index: 0, value: 0 }, { index: 1, value: null }, { index: 2, value: null }, { index: 3, value: null }, { index: 4, value: 10 } Após utilizar o método de preenchimento
linearpara preencher os valoresnull, os documentos tornam-se:{ index: 0, value: 0 }, { index: 1, value: 2.5 }, { index: 2, value: 5 }, { index: 3, value: 7.5 }, { index: 4, value: 10 } nullvalores que não são precedidos e seguidos por valores diferentes denullpermanecemnull.To use the
linearfill method, you must also use the sortBy field to sort your data.
Para um exemplo completo utilizando o método de preenchimento linear, consulte Preencher valores de campo ausentes com interpolação linear.
sortBy Restrições
Ao usar o método de preenchimento linear:
$fillreturns the following error message if different partitions contain identical sortBy values, even when the values do not repeat within a partition:There can be no repeated values in the sort field.
locf Comportamento
locf significa a última observação realizada.
If a field being filled contains both
nulland non-null values,locfsets thenulland missing values to the field's last known non-null value according to the sortBy order.If the field contains only
nullor missing values in a partition,locfsets the field value tonullfor that partition.nulle os valores de campo ausentes que aparecem antes dos valores não nulos na ordem de classificação permanecemnull.
To use the
locffill method, you must also use the sortBy field to sort your data.
Para um exemplo completo utilizando o método de preenchimento locf, consulte Preencher Valores de Campo Faltando Baseado no Último Valor Observado.
Comparação de $fill e Operadores de Agregação
Para preencher null e os valores de campo ausentes em um documento, você pode usar:
Os operadores de agregação
$linearFille$locf.Quando você
$linearFillou$locf, você pode configurar valores para um campo diferente do campo utilizado como os dados de origem.
Exemplos
The examples in this section show how to use $fill to fill missing values:
Preencher valores de campo ausentes com um valor constante
Uma loja de calçados mantém uma coleção dailySales que contém um documento resumindo as vendas de cada dia. A loja de sapatos vende estes tipos de sapatos:
bootssandalssneakers
Crie a seguinte coleção do 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 } ] )
Nem todos os documentos na coleção dailySales contêm cada tipo de sapato. Se um tipo de sapato estiver faltando, significa que não havia sapatos desse tipo vendidos na data correspondente.
The following example uses $fill to set the quantities sold to 0 for the missing shoe types for each day's sales:
db.dailySales.aggregate( [ { $fill: { output: { "bootsSold": { value: 0 }, "sandalsSold": { value: 0 }, "sneakersSold": { value: 0 } } } } ] )
No pipeline anterior:
$fillpreenche valores para campos em falta.saída especifica:
Os nomes dos campos para preencher.
- O valor para definir os campos preenchidos. Neste exemplo, o
- saída especifica um valor constante de
0.
Saída de exemplo:
[ { _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 } ]
Preencher valores de campo ausentes com interpolação linear
Crie uma coleção stock que contenha os seguintes documentos, que acompanham o preço das ações de uma única empresa em intervalos de hora em 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 } ] )
O campo price está faltando em alguns documentos da coleção.
Para preencher os valores de price ausentes utilizando interpolação linear, utilize $fill com o método de preenchimento linear:
db.stock.aggregate( [ { $fill: { sortBy: { time: 1 }, output: { "price": { method: "linear" } } } } ] )
No pipeline anterior:
$fillpreenche valores para campos em falta.sortBy: { time: 1 }classifica os documentos pelo campotimeem ordem crescente, do mais antigo ao mais recente.saída especifica:
pricecomo o campo para o qual preencher os valores ausentes.{ method: "linear" }como método de preenchimento. O preenchimentolinear- O método preenche os valores
priceausentes usando interpolação linear com base nos valorespriceadjacentes na sequência.
Saída de exemplo:
[ { _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 } ]
Preencher valores de campo ausentes com base no último valor observado
Crie uma coleção restaurantReviews que contenha os seguintes documentos, que armazenam as pontuações das avaliações de um único restaurante ao longo do tempo:
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") } ] )
O campo score está faltando em alguns documentos da coleção.
To populate the missing score fields and ensure that there are no gaps in the data, use $fill. In the following example, $fill uses the locf fill method to fill the missing score values with the previous score in the sequence:
db.restaurantReviews.aggregate( [ { $fill: { sortBy: { date: 1 }, output: { "score": { method: "locf" } } } } ] )
No pipeline anterior:
$fillfills in missingscorevalues.sortBy: { date: 1 }classifica os documentos pelo campodateem ordem crescente, do mais antigo ao mais recente.saída especifica:
scorecomo o campo para o qual preencher os valores ausentes.{ method: "locf" }como método de preenchimento. O preenchimentolocf- O método preenche os valores
scoreausentes com o últimoscoreobservado na sequência.
Saída de exemplo:
[ { _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 } ]
Preencha dados para partições distintas
Consider the previous example with restaurant reviews but instead of tracking a single restaurant, the collection now contains reviews for multiple restaurants.
Crie uma coleção denominada restaurantReviewsMultiple e preencha a coleção com estes 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" } ] )
O campo score está faltando em alguns documentos da coleção.
To populate the missing score fields and ensure that there are no gaps in the data, use $fill. In the following example, $fill uses the locf fill method to fill the missing score values with the previous score in the sequence:
db.restaurantReviewsMultiple.aggregate( [ { $fill: { sortBy: { date: 1 }, partitionBy: { "restaurant": "$restaurant" }, output: { "score": { method: "locf" } } } } ] )
No pipeline anterior:
$fillfills in missingscorevalues.sortBy: { date: 1 }classifica os documentos pelo campodateem ordem crescente, do mais antigo ao mais recente.partitionBy: { "restaurant": "$restaurant" }partições dos dados derestaurant. Existem dois restaurantes:Joe's PizzaeSally's Deli.saída especifica:
scorecomo o campo para o qual preencher os valores ausentes.{ method: "locf" }como método de preenchimento. O preenchimentolocf- O método preenche os valores
scoreausentes com o últimoscoreobservado na sequência.
Saída de exemplo:
[ { _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 se um campo foi preenchido usando $fill
Quando você preenche valores ausentes, a saída não indica se um valor foi preenchido com o operador $fill ou se o valor existia no documento originalmente. Para distinguir entre valores preenchidos e preexistentes, você pode usar um estágio $set antes de $fill e definir um novo campo com base na existência ou não do valor.
Por exemplo, crie uma coleção restaurantReviews que contenha os seguintes documentos, que armazenam as pontuações das avaliações de um restaurante ao longo do tempo:
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") } ] )
O campo score está faltando em alguns documentos da coleção. Você pode preencher os valores score ausentes usando o operador $fill.
Crie um pipeline para executar as seguintes ações:
Use
$setpara adicionar um novo campo a cada documento, indicando se o camposcoredo documento existe antes do operador$fillpreencher os valores. Este novo campo é chamadovalueExisted.Preencha os valores
scoreausentes com o últimoscoreobservado na sequência. O método de preenchimentolocfsignifica "última observação realizada adiante".
O pipeline se assemelha ao seguinte código:
db.restaurantReviews.aggregate( [ { $set: { "valueExisted": { "$ifNull": [ { "$toBool": { "$toString": "$score" } }, false ] } } }, { $fill: { sortBy: { date: 1 }, output: { "score": { method: "locf" } } } } ] )
Observação
Manipulação de valores de zero
Na expressão $ifNull, os valores score são convertidos em strings e, em seguida, em booleanos. A expressão $toBool sempre converte strings em true. Se os valores de score não forem convertidos em strings, os valores de score de 0 terão valueExisted definido para false.
Saída:
[ { _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 } ]
Os exemplos de Node.js nesta página usam a coleção sample_weatherdata.data dos conjuntos de dados de amostra do Atlas. Para aprender como criar um cluster gratuito do MongoDB Atlas e carregar os conjuntos de dados de amostra, consulte Introdução na documentação do driver MongoDB Node.js.
Para usar o driver Node.js do MongoDB para adicionar um estágio $fill a um pipeline de agregação , use o operador $fill em um objeto de pipeline.
O exemplo a seguir cria um pipeline que preenche valores nulos ou ausentes. O pipeline inclui os seguintes estágios:
O estágio
$groupagrupa documentos de entrada por seu campotse calcula a média de cada gruposeaSurfaceTemperature.value.The
$fillstage sorts the grouped data by the_idfield in ascending order and fills null or missingseaSurfaceTemperaturevalues by using linear interpolation.
const pipeline = [ { $group: { _id: "$ts", seaSurfaceTemperature: { $avg: "$seaSurfaceTemperature.value" }, } }, { $fill: { sortBy: { _id: 1 }, output: { seaSurfaceTemperature: { method: "linear" } } } } ]; const cursor = collection.aggregate(pipeline); return cursor;