Home > Net >  MongoDB -- Remove null values in objects inside array
MongoDB -- Remove null values in objects inside array

Time:07-13

I have a sample document with array of objects

[
  { 
    array_a: [{"key1": "val1", "key2": "val2", "key3": null}, ...],
    array_b: [{"key4": "val1", "key5": null, "key6": null}, ...]
  }, 
  ... 
]

How can I remove the keys with null value? To become:

[
  { 
    array_a: [{"key1": "val1", "key2": "val2"}, ...],
    array_b: [{"key4": "val1"}, ...]
  }, 
  ... 
]

CodePudding user response:

A bit long query.

  1. $set

    1.1. (array_a) $map - Iterate array from 1.1.1 and return new array.

    1.1.1. input - $map - Convert each document in array_a to key-value pair array: [{ k: "key1", v: "val1" }].

    1.1.2. $filter - Filter the document (key-value pair) with v is not null.

    1.2. (array_b) Same explanation with 1.1.

  2. $set

    2.1. (array_a) $filter

    2.1.1 input - $map - Iterate each array document in the array to return an array with object.

    2.1.2 cond - Filter the document which is not empty document {}.

    2.2. (array_b) - Same explanation with 2.1.

db.collection.aggregate([
  {
    $set: {
      "array_a": {
        $map: {
          input: {
            $map: {
              input: "$array_a",
              in: {
                $objectToArray: "$$this"
              }
            }
          },
          in: {
            $filter: {
              input: "$$this",
              as: "kv",
              cond: {
                $ne: [
                  {
                    "$getField": {
                      "field": "v",
                      "input": "$$kv"
                    }
                  },
                  null
                ]
              }
            }
          }
        }
      },
      "array_b": {
        $map: {
          input: {
            $map: {
              input: "$array_b",
              in: {
                $objectToArray: "$$this"
              }
            }
          },
          in: {
            $filter: {
              input: "$$this",
              as: "kv",
              cond: {
                $ne: [
                  {
                    "$getField": {
                      "field": "v",
                      "input": "$$kv"
                    }
                  },
                  null
                ]
              }
            }
          }
        }
      }
    }
  },
  {
    $set: {
      "array_a": {
        $filter: {
          input: {
            $map: {
              input: "$array_a",
              in: {
                $arrayToObject: "$$this"
              }
            }
          },
          cond: {
            $ne: [
              "$$this",
              {}
            ]
          }
        }
      },
      "array_b": {
        $filter: {
          input: {
            $map: {
              input: "$array_b",
              in: {
                $arrayToObject: "$$this"
              }
            }
          },
          cond: {
            $ne: [
              "$$this",
              {}
            ]
          }
        }
      }
    }
  }
])

Sample Mongo Playground

Note: The $set stages can combine into one, separate into multiple stages for better readable.

  • Related