$fill

A etapa $fill é usada para preencher valores ausentes ou nulos em documentos no pipeline de agregação. Ela oferece vários métodos para preencher dados ausentes, incluindo o uso de valores estáticos, interpolação linear ou valores de documentos anteriores/seguintes.

Sintaxe

{
  $fill: {
    sortBy: <sort specification>,
    partitionBy: <partition fields>,
    partitionByFields: <array of partition field names>,
    output: {
      <field1>: { value: <expression> },
      <field2>: { method: <string> }
    }
  }
}

Parâmetros

Parâmetro Description
sortBy Especifica a ordem de classificação dos documentos ao aplicar métodos de preenchimento que dependem da ordem dos documentos.
partitionBy Optional. Agrupa documentos em partições. As operações de preenchimento são aplicadas separadamente em cada partição.
partitionByFields Optional. Sintaxe alternativa para partitionBy usando uma matriz de nomes de campos.
output Especifica os campos a preencher e o método ou valor a ser usado para preencher dados ausentes.

Métodos de preenchimento

Método Description
value Preencher com um valor estático ou resultado de expressão especificado.
linear Preencher usando interpolação linear entre valores conhecidos (somente campos numéricos).
locf Last Observation Carried Forward - usar o último valor conhecido.
linear Interpolação linear entre valores ao redor.

Exemplos

Considere este documento de exemplo da coleção de documentos das lojas.

{
  "_id": "2cf3f885-9962-4b67-a172-aa9039e9ae2f",
  "name": "First Up Consultants | Bed and Bath Center - South Amir",
  "location": {
    "lat": 60.7954,
    "lon": -142.0012
  },
  "staff": {
    "totalStaff": {
      "fullTime": 18,
      "partTime": 17
    }
  },
  "sales": {
    "totalSales": 37701,
    "salesByCategory": [
      {
        "categoryName": "Mattress Toppers",
        "totalSales": 37701
      }
    ]
  },
  "promotionEvents": [
    {
      "eventName": "Price Drop Palooza",
      "promotionalDates": {
        "startDate": {
          "Year": 2024,
          "Month": 9,
          "Day": 21
        },
        "endDate": {
          "Year": 2024,
          "Month": 9,
          "Day": 30
        }
      },
      "discounts": [
        {
          "categoryName": "Bath Accessories",
          "discountPercentage": 18
        },
        {
          "categoryName": "Pillow Top Mattresses",
          "discountPercentage": 17
        }
      ]
    }
  ]
}

Exemplo 1: Preencher valores ausentes com valor estático

Essa consulta preenche valores ausentes totalSales na salesByCategory matriz com um valor padrão de 0.

db.stores.aggregate([{
    $match: {
        company: {
            $in: ["First Up Consultants"]
        }
    }
}, {
    $unwind: "$sales.salesByCategory"
}, {
    $fill: {
        output: {
            "sales.salesByCategory.totalSales": {
                value: 0
            }
        }
    }
}, {
    $group: {
        _id: "$_id",
        name: {
            $first: "$name"
        },
        salesByCategory: {
            $push: "$sales.salesByCategory"
        }
    }
}])

Os dois primeiros resultados retornados por essa consulta são:

[
    {
        "_id": "affdc09c-7356-4fff-a857-e8301f57159c",
        "name": "First Up Consultants | Sports Gear Pantry - Wildermanhaven",
        "salesByCategory": [
            {
                "categoryName": "Baseball Gear",
                "totalSales": 33878
            },
            {
                "categoryName": "Volleyball Gear",
                "totalSales": 34031
            }
        ]
    },
    {
        "_id": "1cf667b4-d8ce-4f1a-bad1-a1f0bbce26c2",
        "name": "First Up Consultants | Picture Frame Variety - New Abrahamborough",
        "salesByCategory": [
            {
                "categoryName": "Picture Hanging Supplies",
                "totalSales": 7229
            },
            {
                "categoryName": "Collage Frames",
                "totalSales": 40014
            }
        ]
    }
]

Exemplo 2: Preencher dados ausentes de funcionários usando a última observação levada para frente

Essa consulta preenche dados de equipe de part-time ausentes usando o último valor conhecido em cada grupo de repositórios.

db.stores.aggregate([{
    $fill: {
        sortBy: {
            "_id": 1
        },
        output: {
            "staff.totalStaff.partTime": {
                method: "locf"
            }
        }
    }
}, {
    $project: {
        name: 1,
        "staff.totalStaff": 1
    }
}])

Os dois primeiros resultados retornados por essa consulta são:

[
    {
        "_id": "00003278-4226-4ca7-871d-e80d8f414431",
        "name": "Wide World Importers | Camera Depot - Lake Luramouth",
        "staff": {
            "totalStaff": {
                "fullTime": 20,
                "partTime": 6
            }
        }
    },
    {
        "_id": "00009bd0-c44e-4cc8-ab03-347076d74a1a",
        "name": "Wide World Importers | Music Stop - Rebeccaside",
        "staff": {
            "totalStaff": {
                "fullTime": 9,
                "partTime": 0
            }
        }
    }
]

Exemplo 3: Preencher percentuais de desconto ausentes com valor médio

Essa consulta preenche percentuais de desconto ausentes com a porcentagem média de desconto em todas as lojas.

db.stores.aggregate([
  { $unwind: "$promotionEvents" },
  { $unwind: "$promotionEvents.discounts" },
  {
    $fill: {
      partitionBy: "$promotionEvents.eventName",
      sortBy: { "promotionEvents.discounts.categoryName": 1 },
      output: {
        "promotionEvents.discounts.discountPercentage": { 
          value: { $avg: "$promotionEvents.discounts.discountPercentage" } 
        }
      }
    }
  },
  {
    $group: {
      _id: { storeId: "$_id", eventName: "$promotionEvents.eventName" },
      storeName: { $first: "$name" },
      eventName: { $first: "$promotionEvents.eventName" },
      discounts: { $push: "$promotionEvents.discounts" }
    }
  }
])

Os dois primeiros resultados retornados por essa consulta são:

[
    {
        "_id": {
            "storeId": "70d4cc90-23b1-46e3-8f59-630648e311a4",
            "eventName": "Price Slash Spectacular"
        },
        "storeName": "Wide World Importers | Music Bazaar - West Johnpaulhaven",
        "eventName": "Price Slash Spectacular",
        "discounts": [
            {
                "categoryName": "CDs",
                "discountPercentage": 22
            },
            {
                "categoryName": "Vinyl Records",
                "discountPercentage": 21
            }
        ]
    },
    {
        "_id": {
            "storeId": "24873ac4-b2d1-4216-a425-3375a384b23d",
            "eventName": "Massive Deal Mania"
        },
        "storeName": "Northwind Traders | Furniture Pantry - Farrellchester",
        "eventName": "Massive Deal Mania",
        "discounts": [
            {
                "categoryName": "Bookcases",
                "discountPercentage": 22
            },
            {
                "categoryName": "Cabinets",
                "discountPercentage": 8
            }
        ]
    }
]

Casos de uso

  • Limpeza de Dados: Preencher valores ausentes em conjuntos de dados importados
  • Dados de Séries Temporais: Lidar com lacunas em dados sequenciais usando interpolação
  • Valores Padrão: Atribuir valores padrão a campos opcionais
  • Normalização de Dados: Garantir uma estrutura de dados consistente em todos os documentos