Function: removeObjectStubs

      +

      Goal: Recursively remove all empty object stubs from a document.

      • This function removeObjectStubs will recursively prune empty objects 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".

      • The removeEmptyParts function returns two (2) values in an array the doc and a flag indicating if a change has occurred. This flag ary_obj_upd[1] will increase the performance of subsequent runs where the Feed boundary is set to Everything on large document sets.

      • This function is a subset of the cleanup functionality found in the Scriptlet removeNullsAndEmptys.

      • removeObjectStubs

      • Input Data/Mutation

      • Output Data/Mutation

      // To run configure the settings for this Function, removeObjectStubs, 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 removeEmptyParts(ary_obj_upd) {
          if (ary_obj_upd[0] !== null && typeof ary_obj_upd[0] == "object") {
              Object.entries(ary_obj_upd[0]).forEach(([k, v]) => {
                  if (ary_obj_upd[0][k] && typeof ary_obj_upd[0][k] === 'object') {
                      // recurse
                      if (removeEmptyParts(
                          [ary_obj_upd[0][k],ary_obj_upd[1]])[1] == true) {
                          ary_obj_upd[1] = true;
                      }
                      // remove stub {} object items
                      if (ary_obj_upd[0][k] && !Array.isArray(ary_obj_upd[0][k]) &&
                          Object.keys(ary_obj_upd[0][k]).length === 0
                      ) {
                          delete(ary_obj_upd[0][k]) // 6.6+ can use "delete obj"
                          ary_obj_upd[1] = true;
                      }
                  }
              });
          } else {
              // obj is a number or a string
          }
          // return [ary_obj_upd[0],ary_obj_upd[1]];
          return ary_obj_upd;
      }
      
      function OnUpdate(doc, meta) {
          // optional filter to specific types
          if (doc.type !== "my_data_to_prune") return;
      
          // try make a new doc without {} stubs
          var altered = false;
          var ary_obj_upd = removeEmptyParts([doc,altered]);
          if (ary_obj_upd[1]) {
              // We actualy did an update so we need to write to KV
              // Note, the alias src_col (mode r+w) references the
              // handlers source collection (allowed version 6.5+).
              src_col[meta.id] = ary_obj_upd[0];
          }
      }
      INPUT: KEY my_data_to_prune::1001
      
      {
        "type": "my_data_to_prune",
        "root": {
          "field1a": {},
          "field1b": {
            "field2a": {
              "value": 2
            }
          },
          "field1c": {
            "field2c": {
              "value": 3,
              "field3c": {
                  "value": 4,
                  "field4c": {}
              }
            }
          }
        }
      }
      UPDATED/OUTPUT: KEY my_data_to_prune::1001
      
       {
        "type": "my_data_to_prune",
        "root": {
          "field1b": {
            "field2a": {
              "value": 2
            }
          },
          "field1c": {
            "field2c": {
              "value": 3,
              "field3c": {
                "value": 4
              }
            }
          }
        }
      }