In a collection called test
I have some documents that are similar to:
{
"_id" : "PRQA2311",
"name": "Binder",
"category": "Office Supplies",
"price": 3.99,
"...": "...",
"variants" : [
{
"barcode" : "2314399903212",
"attributes" : {
"color" : "red",
"size" : "Letter"
}
},
{
"barcode" : "2314399903213",
"attributes" : {
"color" : "red",
"size" : "A4"
}
},
{
"barcode" : "2314399903214",
"attributes" : {
"color" : "blue",
"size" : "Letter"
}
},
{
"barcode" : "2314399903215",
"attributes" : {
"color" : "blue",
"size" : "A4"
}
}
]
}
and I use the following aggregation pipeline to split and regroup them so that each product has only one color:
db.test.aggregate([
{
$unwind: "$variants"
},
{
$group: {
_id: {
$concat: [
{ "$toString": "$_id" },
".",
{ "$toString": "$variants.attributes.color" }
]
},
name: { $first: "$name" },
variants: { $push: "$variants" }
}
}
]).pretty();
This works fine, but I would also like to copy the other fields. While I can do this by explicitly adding the fields to the group aggregation like I have done with the name
field. It would make development and maintenance easier if I could just copy all of the fields.
Looking at the accepted answer of this question it seems like it might not have been possible in the past. However the second answer hints that it might be possible with newer versions of MongoDB, even though the provided solution is not immediately applicable to my problem.
I think a solution might be possible with $mergeObjects
and $replaceRoot
, but I haven't been able to work it out yet.