Function: removeNullObjectsAndElements

      +

      Goal: Recursively remove all nulls and empty items from a document.

      • This function removeNullObjectsAndElements will recursively prune nulls and empty items from a given JSON document.

      • Requires Eventing Storage (or metadata collection) and a "source" collection.

      • Will operate on all documents where doc.type === "my_data_to_prune".

      • This function is a superset of the cleanup functionality found in the Scriptlet removeObjectStubs.

      • removeNullObjectsAndElements

      • Input Data/Mutation

      • Output Data/Mutation

      // To run configure the settings for this Function, removeNullObjectsAndElements, as follows:
      //
      // Version 7.1+
      //   "Function Scope"
      //     *.* (or try bulk.data if non-privileged)
      // Version 7.0+
      //   "Listen to Location"
      //     bulk.data.source
      //   "Eventing Storage"
      //     rr100.eventing.metadata
      //   Binding(s)
      //    1. "binding type", "alias name...", "bucket.scope.collection", "Access"
      //       "bucket alias", "src_col",       "bulk.data.source",        "read and write"
      //
      // Version 6.X
      //   "Source Bucket"
      //     source
      //   "MetaData Bucket"
      //     metadata
      //   Binding(s)
      //    1. "binding type", "alias name...", "bucket", "Access"
      //       "bucket alias", "src_col",       "source", "read and write"
      
      function removeNullParts(obj) {
          // remove any null Objects
          Object.keys(obj).forEach(k =>
              (obj[k] && typeof obj[k] === 'object') && removeNullParts(obj[k]) ||
              (!obj[k] && obj[k] !== undefined) && delete(obj[k]) // 6.6+ can use "delete obj[k]""
          );
          Object.keys(obj).forEach(k =>
              (obj[k] && Array.isArray(obj[k])) &&
              (obj[k] = obj[k].filter(element => element !== null))
          );
          return obj;
      }
      
      function removeEmptyParts(obj) {
          if (obj !== null && typeof obj == "object") {
              Object.entries(obj).forEach(([k, v]) => {
                  if (obj[k] && typeof obj[k] === 'object') {
                      // recurse
                      removeEmptyParts(obj[k])
                      // collapse out null's in Array if any
                      if (obj[k] && Array.isArray(obj[k])) {
                          obj[k] = obj[k].filter(element => element !== null)
                      }
                      // remove empty [] array items and {} object items
                      if (
                          (obj[k] && Array.isArray(obj[k]) && obj[k].length === 0) ||
                          (obj[k] && !Array.isArray(obj[k]) && Object.keys(obj[k]).length === 0)
                      ) {
                          delete(obj[k]) // 6.6+ can use "delete obj"
                      }
                  }
              });
          } else {
              // obj is a number or a string
          }
          return obj;
      }
      
      function OnUpdate(doc, meta) {
          if (doc.type !== "my_data_to_prune") return;
      
          // make a new doc without any nulls
          var newdoc = removeNullParts(doc);
          // make a new doc without {} [] empties
          newdoc = removeEmptyParts(newdoc);
      
          // alias src_col to our source collection. Since rev 6.5+ allowed to be in r/w mode
          src_col[meta.id] = newdoc;
      }
      INPUT: KEY my_data_to_prune::1001
      
      {
        "type": "my_data_to_prune",
        "id": 1001,
        "a_first_super_long_name_right_here": 111,
        "b": "my object",
        "c": "",
        "d": null,
        "f": {
          "v": 1,
          "x": "",
          "y": null,
          "m": {
            "a": "asd"
          }
        },
        "f2": {
          "v": 1,
          "x": "",
          "y": null,
          "m": {
            "a": "asd",
            "b": null,
            "c": null,
            "a_second_super_long_name_right_here": 222,
            "ary1": [
              null,
              1,
              null,
              2,
              null,
              3
            ],
            "ary2": [
              [
                1,
                2
              ],
              [
                3,
                4
              ],
              [
                5,
                null,
                6
              ],
              {
                "a": 1
              },
              {
                "b": 2
              },
              {
                "c": 3,
                "d": null
              },
              {
                "e": null
              },
              [
                null,
                null,
                null,
                null
              ]
            ]
          }
        },
        "a_third_super_long_name_right_here": {
          "x": 1,
          "y": 2,
          "z": null
        }
      }
      UPDATED/OUTPUT: KEY my_data_to_prune::1001
      
      {
        "type": "my_data_to_prune",
        "id": 1001,
        "a_first_super_long_name_right_here": 111,
        "b": "my object",
        "f": {
          "v": 1,
          "m": {
            "a": "asd"
          }
        },
        "f2": {
          "v": 1,
          "m": {
            "a": "asd",
            "a_second_super_long_name_right_here": 222,
            "ary1": [
              1,
              2,
              3
            ],
            "ary2": [
              [
                1,
                2
              ],
              [
                3,
                4
              ],
              [
                5,
                6
              ],
              {
                "a": 1
              },
              {
                "b": 2
              },
              {
                "c": 3
              }
            ]
          }
        },
        "a_third_super_long_name_right_here": {
          "x": 1,
          "y": 2
        }
      }