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