Menu Docs
Página inicial do Docs
/
Manual do MongoDB
/ / /

$fill (agregação)

Nesta página

  • Definição
  • Sintaxe
  • Comportamento e restrições
  • partitionByFields Restrições
  • linear Comportamento
  • locf 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
$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.

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

partitionBy

Opcional

Especifica uma expressão para agrupar os documentos. Na etapa, um grupo de $fill documentos é conhecido como uma partição.

Se você omitir partitionBy e partitionByFields, o usará uma partição para toda a$fill coleção.

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 $fill documentos é conhecido como uma partição.

Se você omitir partitionBy e partitionByFields, o usará uma partição para toda a$fill coleção.

partitionBy e partitionByFields são mutuamente exclusivos.

partitionByFields Consulte Restrições do.

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 $sort.

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 value ou method. Se o nome for:

$fill retorna um erro se houver algum nome de campo na array partitionByFields:

  • Avalia para um valor não string.

  • Começa com $.

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, o linearFill utiliza:

    • A diferença entre os valores circundantes que não sãonull.

    • O número de null campos para preencher entre os valores circundantes.

  • O método linear pode preencher vários valores de null 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 valores null, 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 permanecem null.

  • Para usar o método de preenchimento linear, você também deve usar o campo sortBy para classificar os dados.

    • Ao usar o método de preenchimento linear, $fill retorna um erro se houver algum valor repetido no campo sortBy em uma única partição.

Para um exemplo completo utilizando o método de preenchimento linear, consulte Preencher valores de campo ausentes com interpolação linear.

locf significa a última observação realizada.

  • Se um campo que está sendo preenchido contiver valores null e não nulos, locf definirá os valores null 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 como null para essa partição.

    • null e os valores de campo ausentes que aparecem antes dos valores não nulos na ordem de classificação permanecem null.

  • 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.

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.

Os exemplos nesta seção mostram como utilizar o $fill para preencher valores ausentes:

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
}
]

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 campo time 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. O linear método de preenchimento preenche os price valores ausentes usando interpolação linear com base nos price 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
}
]

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 de score.

  • sortBy: { date: 1 } classifica os documentos pelo campo date 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 preenchimento locf preenche os valores score ausentes com o último score 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
}
]

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 de score.

  • sortBy: { date: 1 } classifica os documentos pelo campo date em ordem crescente, do mais antigo ao mais recente.

  • partitionBy: { "restaurant": "$restaurant" } partições dos dados de restaurant. Existem dois restaurantes: Joe's Pizza e Sally'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 preenchimento locf preenche os valores score ausentes com o último score 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
}
]

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 campo score do documento existe antes do operador $fill preencher os valores. Este novo campo é chamado valueExisted.

  • Preencha os valores score ausentes com o último score observado na sequência. O método de preenchimento locf 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

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
}
]

Voltar

$facet