Goal: Recursively and Generically Rename Keys in a document.
- 
This function genericRename shows how a document can have its keys or fields renamed.
 - 
Requires Eventing Storage (or metadata collection), a "source" collection, and a "destination" collection.
 - 
Will operate on all documents where doc.type === "my_data_to_rename".
 - 
Will write transformed or flattened documents to the destination collection with the same type and id.
 - 
The destination collection can be shared (or replicated via XCDR to a business partner - maybe to AWS, GCP, or Azure).
 - 
Will also remove the transformed document in the destination collection when the original source document is removed.
 - 
Note since the document is not available during an OnDelete we will filter by KEY prefix starting with "my_data_to_rename:".
 
- 
genericRename
 - 
Input Data/Mutation
 - 
Output Data/Mutation
 
// To run configure the settings for this Function, genericRename, 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", "dst_col",       "bulk.data.destination",   "read and write"
//
// Version 6.X
//   "Source Bucket"
//     source
//   "MetaData Bucket"
//     metadata
//   Binding(s)
//    1. "binding type", "alias name...", "bucket",     "Access"
//       "bucket alias", "dst_col",       "destinaton", "read and write"
function renamePartsByMap(obj, rename_map) {
    if (obj !== null && typeof obj == "object") {
        Object.entries(obj).forEach(([k, v]) => {
            if (obj[k] && typeof obj[k] === 'object') {
                // recurse
                renamePartsByMap(obj[k], rename_map)
            }
            if (obj[k]) {
                // recurse
                var tst = rename_map[k];
                if (tst) {
                    if (tst !== undefined && tst !== null) {
                        obj[rename_map[k]] = obj[k];
                        delete(obj[k]);
                    }
                }
            }
        });
    }
    return obj;
}
function OnUpdate(doc, meta) {
    if (doc.type !== "my_data_to_rename") return;
    // rename long fields to shorter names using a MAP
    var rename_map = {
        "a_first_super_long_name_right_here": "a_short1",
        "a_second_super_long_name_right_here": "a_short2",
        "a_third_super_long_name_right_here": "a_short3"
    };
    var newdoc = renamePartsByMap(doc, rename_map);
    // alias dst_col to our source collection. Since rev 6.5+ allowed to be in r/w mode
    dst_col[meta.id] = newdoc;
}
function OnDelete(meta, options) {
    // filter
    if (!(meta.id.startsWith("my_data_to_rename:"))) return;
    log("OnDelete expired=" + options.expired +" REM id: "+meta.id);
    try {
        delete dst_col[meta.id];
    } catch (e) {
        log("Error on delete: "+e+", id:",meta.id);
    }
}
in keyspace bulk.data.source
INPUT: KEY my_data_to_rename::1001
{
  "type": "my_data_to_rename",
  "id": 1001,
  "a_first_super_long_name_right_here": 111,
  "b": "my object",
  "c": "",
  "d": null,
  "f": {
    "m": {
      "a": "asd"
    }
  },
  "f2": {
    "m": {
      "a": "asd",
      "a_second_super_long_name_right_here": 222,
      "ary1": [
        {
          "a_second_super_long_name_right_here": 1
        },
        {
          "a_second_super_long_name_right_here": 2
        },
        [
          {
            "a_second_super_long_name_right_here": 1
          },
          {
            "a_second_super_long_name_right_here": 2
          }
        ]
      ]
    }
  },
  "a_third_super_long_name_right_here": {
    "x": 1,
    "y": 2,
    "not_a_key_will_not_change": "a_third_super_long_name_right_here"
  }
}
in keyspace bulk.data.destination
UPDATED/OUTPUT: KEY my_data_to_rename::1001
{
  "type": "my_data_to_rename",
  "id": 1001,
  "b": "my object",
  "c": "",
  "d": null,
  "f": {
    "m": {
      "a": "asd"
    }
  },
  "f2": {
    "m": {
      "a": "asd",
      "ary1": [
        {
          "a_short2": 1
        },
        {
          "a_short2": 2
        },
        [
          {
            "a_short2": 1
          },
          {
            "a_short2": 2
          }
        ]
      ],
      "a_short2": 222
    }
  },
  "a_short1": 111,
  "a_short3": {
    "x": 1,
    "y": 2,
    "not_a_key_will_not_change": "a_third_super_long_name_right_here"
  }
}