Various modifications are being done with the subdoc API. However, the delete creates an issue. I need to remove elements at the “field2” layer. However, when a given node at the “field1” layer has no more children left, it will be left hanging:
{
"root": {
"field1a": {}, // field1a here is empty
"field1b": {
"field2a": {
"value": 2
}
}
},
}
Since some logic may rely on the existence of certain keys, I need to clean up these empty path stubs. I can obviously iterate through and check this, and then delete any childless nodes. However I’m wondering if there is a cleaner way to do this. I am implementing a bunch of such deletes at different layers, and it seems a little bit cumbersome to iterate through and check whether everything has children.
There’s no conditional logic in Sub-Document (“delete field1a iff empty”), so I don’t think there’s a way to do this. For this kind of complex operation it’s simpler to do a full-document get-and-replace.
function OnUpdate(doc, meta) {
// optional filter to specific types
// if (doc.type !== "my_data_to_prune") return;
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])
// remove stub {} object items
if (obj[k] && !Array.isArray(obj[k]) &&
Object.keys(obj[k]).length === 0
) {
delete(obj[k]) // 6.6+ can use "delete obj"
updated = true; // set in scope OnUpdate
}
}
});
} else {
// obj is a number or a string
}
return obj;
}
// make a new doc without {} stubs
var updated = false;
var newdoc = removeEmptyParts(doc);
// Requires 6.5+, src_bkt aliased to source bucket mode r+w
if (updated) {
// only update the KV if we updated the doc
src_bkt[meta.id] = newdoc;
}
}
Like I said above function can be run (deployed with a feed boundary set to Everything and then undeployed) as a point tool to clean up all items in a bucket, or it can be run continuously to repair these sort of issues upon any mutation.