0

This is how the Order model is structured

new Schema(
  {
    ...
    products: [
      {
        _id: String,
        title: String,
        image: [String],
        category: String,
        purity: String,
        metal: String,
        weight: String,
        gemstone: {
          weight: Number,
          category: String,
          purity: String,
          shape: String,
          color: String,
          clarity: String,
        },
        qty: Number,
        price: Number,
      },
    ],
    user: {type: String},
    shop: { type: String, required: true },
    type: { type: String, required: true, enum: ["product", "scheme"] },
  }
Now I need to query data based on a shopId and type: "product". But I want the operation to return data in the following format
[
  {
    category: "ring",
    products: [{...productObject, users: [userIds]}],
  }
]

Rest of the fields are not needed. So basically I want to group users for each product and then group products according to category that each product has.

I know I can just query the data directly and then perform a bunch of array operations to somehow get data like this. I was just wondering if we could use aggregate to do all this in a single opearation and make it more performant.

I should let you know that this is in a separate microservice using a different database so I can't directly just link Ids. All data is supposed to taken from this model with no external joins.

I have tried this aggregate query

orders = await Order.aggregate([
        {
          $match: {
            shop: shopId,
            type: "product",
          },
        },
        {
          $unwind: "$products",
        },
        {
          $group: {
            _id: "$products.category",
            products: {
              $push: {
                users: "$user",
                product: "$products",
              },
            },
          },
        },
        {
          $project: {
            _id: false,
            category: "$_id",
            products: 1,
          },
        },
      ]);

This returns data like this

[
 {
  category: "ring",
  products: [
   { 
     users: "63761866b2e154f25fcebd95",
     product: {
       ...,
       _id: "6375ff628fbcdb23c333ee48"
     }
   },
   {
     users: "637605b0b2e154f25fceb520",
     product: {
       ...,
       _id: "6375ff628fbcdb23c333ee48",
     }
    },
    {
     users: "637605b0b2e154f25fceb520",
     product: {
       ...,
       _id: "6375ff5d8fbcdb23c333ee44",
     }
    },
    {
     users: "63761866b2e154f25fcebd95",
     product: {
       ...,
       _id: "6375ff5d8fbcdb23c333ee44",
     }
    },
    {
     users: "63761866b2e154f25fcebd95",
     product: {
       ...,
       _id: "6375ff628fbcdb23c333ee48",
     }
    }
   ]
 }
]

As you can see I am able to group by category but I still want to merge products with same _id and make the users as an array for the different ids. Also it would be great if I could avoid the extra product field in products array and just combine users with products elements.

Basically, the above should look like this

[
 {
   category: "ring",
   products: [
     {
      ...productDetails,
      _id: "6375ff628fbcdb23c333ee48",
      users: ["63761866b2e154f25fcebd95", "637605b0b2e154f25fceb520"]
     },
     {
       ...productDetails,
       _id: "6375ff5d8fbcdb23c333ee44",
       users: ["63761866b2e154f25fcebd95", "637605b0b2e154f25fceb520"]
     }
   ]
 }
]

Any help is appreciated! If possible please do explain your operation!

0 Answers0