0

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.

1 Answer 1

1

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"
          }
        }
      }
    }
}}

Playground

Sign up to request clarification or add additional context in comments.

1 Comment

Joe, Thank you very much for the reply. I tried your solution, but having difficulty how to implement the $reduce here. { $reduce: { input: skus, initialValue: , in: }}..If you have some time, can you explain a little more about this? But anyway, thanks again.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.