I am currently doing a project where my Database Management System is MongoDB. I am writing an aggregation pipeline where there are several stages. I am currently struggling at a particular stage where I want to obtain the following output. MongoDB has so many operator expressions that I am confused about which one to use to achieve this. I have a collection called Styles and Skus which are as follows:
// Schema for styles
const styles = mongoose.Schema({
id: Number,
productId: Number,
name: String,
sale_price: String,
original_price: String,
default_price: Boolean,
}, {
strict: false,
});
// Schema for skus
const skus = mongoose.Schema({
id: Number,
styleId: Number,
size: String,
quantity: String,
}, {
strict: false,
});
Each style can have several SKUs, one-to-many relationships. In my aggregation pipeline, I am using $lookup to find all the SKUs of that particular style and adding a new field called SKUs in the styles document. I am getting results like this after the $lookup.
{
"style_id": 1,
"name": "Forest Green & Black",
"original_price": "140",
"sale_price": "0",
"default?": true,
"skus": [
{
"id": 37,
"styleId": 1,
"size": "XS",
"quantity": 16
},
{
"id": 38,
"styleId": 1,
"size": "S",
"quantity": 8
}
]
}
Which is expected as $lookup returns a matching array. But I want my Styles document to look like this.
{
"style_id": 1,
"name": "Forest Green & Black",
"original_price": "140",
"sale_price": "0",
"default?": true,
"skus": {
"37": {
"styleId": 1,
"size": "XS",
"quantity": 16
},
"38": {
"styleId": 1,
"size": "S",
"quantity": 8
}
}
}
Can someone give any idea how to structure the data like above in aggregation pipeline? Any help would be greatly appreciated. Thanks in advance.
CodePudding user response:
You could use $map
or $reduce
to convert the objects in the array to the form
[
{
k: <key1>
v: <value1>
},
{
k: <key2>
v: <value2>
}
]
Then use $arrayToObject
which will convert the array to an object like:
{
<key1>: <value1>,
<key2>: <value2>
}
Together, this might look like:
{$addFields: {
skus: {
$arrayToObject: {
$map: {
input: "$skus",
in: {
k: {$toString: "$$this.id"},
v: "$$this"
}
}
}
}
}}