Im writing a mongodb aggregate pipeline. My documents are of the form below :
{
name: "01"
tags {
tag_01: {
a: "a01-val",
b: "b01-val"
},
tag_02: {
a: "a02-val",
b: "b02-val"
}
}
},
{
name: "02"
tags {
tag_03: {
a: "a03-val",
b: "b03-val"
},
tag_04: {
a: "a04-val",
b: "b04-val"
}
}
}
My pipeline should generate documents as below :
{
name: "01"
tags {
tag_01: {
a: "a01-val",
b: "b01-val",
tagName: "tag_01"
},
tag_02: {
a: "a02-val",
b: "b02-val",
tagName: "tag_02"
}
}
},
{
name: "02"
tags {
tag_03: {
a: "a03-val",
b: "b03-val",
tagName: "tag_03"
},
tag_04: {
a: "a04-val",
b: "b04-val",
tagName: "tag_04"
}
}
}
In other words, a new field is added inside each subdocument whose value is the name of the parent field. Is it possible to do this?
Use $objectToArray
to convert tags
into an array of k-v tuples. Use $map
to iterate through the array elements and $mergeObjects
to set the field with k
. Then use $arrayToObject
to revert back to original object form.
db.collection.update({},
[
{
"$set": {
"tags": {
"$objectToArray": "$tags"
}
}
},
{
"$set": {
"tags": {
"$map": {
"input": "$tags",
"as": "tag",
"in": {
k: "$$tag.k",
v: {
"$mergeObjects": [
"$$tag.v",
{
"tagName": "$$tag.k"
}
]
}
}
}
}
}
},
{
$set: {
tags: {
"$arrayToObject": "$tags"
}
}
}
],
{
multi: true
})