$fill (agregação)
Nesta página
- Definição
- Sintaxe
- Comportamento e restrições
partitionByFields
Restriçõeslinear
Comportamentolocf
Comportamento- Comparação de
$fill
e operadores de agregação - Exemplos
- Preencher valores de campo ausentes com um valor constante
- Preencher valores de campo ausentes com interpolação linear
- Preencher valores de campo ausentes com base no último valor observado
- Preencha dados para partições distintas
- Indique se um campo foi preenchido usando
$fill
Definição
$fill
Novidades na versão 5.3.
Preenche
null
e os valores de campo ausentes nos documentos.Você pode utilizar o
$fill
para 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 umaexpressão para agrupar os documentos. No estágio Se você omitir partitionBy e partitionByFields, partitionBy e partitionByFields são mutuamente exclusivos. Veja um exemplo. | |
Opcional | Especifica um array de campos como a chave composta para agrupar os documentos. Na etapa Se você omitir partitionBy e partitionByFields, partitionBy e partitionByFields são mutuamente exclusivos. Consulte Restrições | |
Necessário se o método for especificado em pelo menos uma saída.<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
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 é
null
ou ausente,linearFill
preenche esses campos na proporção do intervalo de valores ausentes entre os valores não circundantes,null
de acordo com a ordem SortBy . Para determinar os valores para campos ausentes, olinearFill
utiliza:A diferença entre os valores circundantes que não são
null
.O número de
null
campos para preencher entre os valores circundantes.
O método
linear
pode preencher vários valores denull
consecutivos se esses valores forem precedidos e seguidos por valores nãonull
de 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
linear
para 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 } null
valores que não são precedidos e seguidos por valores diferentes denull
permanecemnull
.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
null
e não nulos,locf
definirá os valoresnull
e ausentes como o último valor não nulo conhecido do campo, de acordo com a ordem sortBy.Se o campo contiver apenas
null
ou valores ausentes em uma partição,locf
definirá o valor do campo comonull
para essa partição.null
e 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
$linearFill
e$locf
.Quando você
$linearFill
ou$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:
boots
sandals
sneakers
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:
$fill
preenche valores para campos em falta.saída especifica:
Os nomes dos campos para preencher.
O valor para definir os campos preenchidos. Neste exemplo, a 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 acompanhe 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:
$fill
preenche valores para campos em falta.sortBy: { time: 1 }
classifica os documentos pelo campotime
em ordem crescente, do mais antigo ao mais recente.saída especifica:
price
como o campo para o qual preencher os valores ausentes.{ method: "linear" }
como método de preenchimento. Olinear
método de preenchimento preenche osprice
valores ausentes usando interpolação linear com base nosprice
valores circundantes 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 do restaurantReviews
que contenha pontuações de avaliações para 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:
$fill
preenche os valores ausentes descore
.sortBy: { date: 1 }
classifica os documentos pelo campodate
em ordem crescente, do mais antigo ao mais recente.saída especifica:
score
como o campo para o qual preencher os valores ausentes.{ method: "locf" }
como método de preenchimento. O método de preenchimentolocf
preenche os valoresscore
ausentes com o últimoscore
observado 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:
$fill
preenche os valores ausentes descore
.sortBy: { date: 1 }
classifica os documentos pelo campodate
em ordem crescente, do mais antigo ao mais recente.partitionBy: { "restaurant": "$restaurant" }
partições dos dados derestaurant
. Existem dois restaurantes:Joe's Pizza
eSally's Deli
.saída especifica:
score
como o campo para o qual preencher os valores ausentes.{ method: "locf" }
como método de preenchimento. O método de preenchimentolocf
preenche os valoresscore
ausentes com o últimoscore
observado 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 pontuações de avaliação para 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á ausente em alguns dos documentos da coleção. Você pode preencher os valores score
ausentes com o operador $fill
.
Crie um pipeline para executar as seguintes ações:
Adicione um novo campo a cada documento (usando
$set
) indicando se o camposcore
do documento existe antes do operador$fill
preencher os valores. Este novo campo é chamadovalueExisted
.Preencha os valores
score
ausentes com o últimoscore
observado na sequência. O método de preenchimentolocf
significa "última observação realizada adiante".
O pipeline tem a seguinte aparência:
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 } ]