Definição
$fillNovidades na versão 5.3.
Preenche
nulle os valores de campo ausentes nos documentos.Você pode utilizar o
$fillpara preencher pontos de dados ausentes:Em uma sequência baseada em valores circundantes.
Com um valor fixo.
Sintaxe
O estágio $fill tem esta sintaxe:
{ $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> }, ... } } }
O estágio $fill toma um documento com estes campos:
Campo | necessidade | Descrição |
|---|---|---|
Opcional | Especifica uma expressão para agrupar os documentos. Na etapa, um grupo de Se você omitir partitionBy e partitionByFields, o usará uma partição para toda a partitionBy e partitionByFields são mutuamente exclusivos. Veja um exemplo. | |
Opcional | Especifica uma array de campos como a chave composta para agrupar os documentos. No estágio, cada grupo de Se você omitir partitionBy e partitionByFields, o usará uma partição para toda a partitionBy e partitionByFields são mutuamente exclusivos. | |
Necessário se o método for especificado em pelo menos uma <field>saída.. 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 | ||
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 retorna um erro se houver algum nome de campo na array partitionByFields:
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.
Para cada documento em que o campo é
nullou ausente,linearFillpreenche esses campos na proporção do intervalo de valores ausentes entre os valores não circundantes,nullde acordo com a ordem SortBy . Para determinar os valores para campos ausentes, olinearFillutiliza: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.Para usar o método de preenchimento
linear, você também deve usar o campo sortBy para classificar os dados.
Para um exemplo completo utilizando o método de preenchimento linear, consulte Preencher valores de campo ausentes com interpolação linear.
locf Comportamento
locf significa a última observação realizada.
Se um campo que está sendo preenchido contiver valores
nulle não nulos,locfdefinirá os valoresnulle ausentes como o último valor não nulo conhecido do campo, de acordo com a ordem sortBy.Se o campo contiver apenas
nullou valores ausentes em uma partição,locfdefinirá o valor do campo comonullpara essa partição.nulle os valores de campo ausentes que aparecem antes dos valores não nulos na ordem de classificação permanecemnull.
Para usar o método de preenchimento
locf, você também deve usar o campo sortBy para classificar os dados.
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:
O estágio
$fill.Quando você utiliza o estágio
$fill, o campo que você especifica na saída é o mesmo campo utilizado como os dados de origem.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
Os exemplos nesta seção mostram como utilizar o $fill para preencher valores ausentes:
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.
O exemplo a seguir usa $fill para definir as quantidades vendidas para 0 para os tipos de sapatos ausentes para as vendas de cada dia:
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.
Para preencher os campos de score ausentes e garantir que não haja lacunas nos dados, use $fill. No exemplo seguinte, $fill usa o método locf para preencher os valores de score ausentes com a score anterior na sequência:
db.restaurantReviews.aggregate( [ { $fill: { sortBy: { date: 1 }, output: { "score": { method: "locf" } } } } ] )
No pipeline anterior:
$fillpreenche os valores ausentes descore.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
Considere o exemplo anterior com avaliações de restaurantes, mas em vez de rastrear um único restaurante, a coleção agora contém avaliações de vários restaurantes.
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.
Para preencher os campos de score ausentes e garantir que não haja lacunas nos dados, use $fill. No exemplo seguinte, $fill usa o método locf para preencher os valores de score ausentes com a score anterior na sequência:
db.restaurantReviewsMultiple.aggregate( [ { $fill: { sortBy: { date: 1 }, partitionBy: { "restaurant": "$restaurant" }, output: { "score": { method: "locf" } } } } ] )
No pipeline anterior:
$fillpreenche os valores ausentes descore.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
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.O estágio
$fillclassifica os dados agrupados pelo campo_idem ordem crescente e preenche valoresseaSurfaceTemperaturenulos ou ausentes usando interpolação linear.
const pipeline = [ { $group: { _id: "$ts", seaSurfaceTemperature: { $avg: "$seaSurfaceTemperature.value" }, } }, { $fill: { sortBy: { _id: 1 }, output: { seaSurfaceTemperature: { method: "linear" } } } } ]; const cursor = collection.aggregate(pipeline); return cursor;