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