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?
2
Answers
Use
$objectToArray
to converttags
into an array of k-v tuples. Use$map
to iterate through the array elements and$mergeObjects
to set the field withk
. Then use$arrayToObject
to revert back to original object form.Mongo Playground
$objectToArray
ontags
, then unwind it to get one record/document per tag / k-v tuples.tagName
field in each of thosev
objects, using the value ofk
in each of the unwound tags.$push
to get an array of the previously unwoundk-v
objects.fieldName: { $first: "$fieldName" }
to add them or use$mergeObjects
with$$ROOT
, depending on how many of them/ease of writing.$arrayToObject
to get tags in the original form.Mongo Playground
PS. For performance, you’re probably better off with ray’s solution.