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