How To Populate objects inside array through aggregation

I got an order document structure like that and I want to populate only product and also add the related options and quantity beside the product object

{
    _id:ObjectId('61c45d25bdf9c1389879db9f'),
    orderItems: [
        {
            options:[
                {
                    _id:ObjectId('61fd914d4a236b94f816c27d'),
                    question: 'lorem ipsum dolor set amet',
                    answer: 'lorem'
                }, {
                    _id: ObjectId('61fd914d4a236b94f816c27d'),
                    question: 'lorem ipsum dolor set amet',
                    answer: 'lorem'
                }, {
                    _id: ObjectId('61fd914d4a236b94f816c27d'),
                    question: 'lorem ipsum dolor set amet',
                    answer: 'lorem'
                }, {
                    _id: ObjectId('61fd914d4a236b94f816c27d'),
                    question: 'lorem ipsum dolor set amet',
                    answer: 'lorem'
                },
            ],
            quantity:4,
            product:ObjectId('61c5e1e7c2ec39450cdf41b7')
        }, {
            options:[
                {
                    _id: ObjectId('61fd914d4a236b94f816c27d'),
                    question: 'lorem ipsum dolor set amet',
                    answer:'lorem'
                }, {
                    _id: ObjectId('61fd914d4a236b94f816c27d'),
                    question: 'lorem ipsum dolor set amet',
                    answer: 'lorem'
                },
                {
                    _id: ObjectId('61fd914d4a236b94f816c27d'),
                    question: 'lorem ipsum dolor set amet',
                    answer: 'lorem'
                }, {
                    _id: ObjectId('61fd914d4a236b94f816c27d'),
                    question: 'lorem ipsum dolor set amet',
                    answer:'lorem'
                },
            ],
            quantity:3,
            product:ObjectId('61c5e1e7c2ec39450cdf41b7')
        }
    ]}

how can i do a query through aggregation and joining with product collection to achieve this final query

{
        _id:ObjectId('61c45d25bdf9c1389879db9f'),
        orderItems: [
            {
                options:[
                    {
                        _id: ObjectId('61fd914d4a236b94f816c27d'),
                        question: 'lorem ipsum dolor set amet',
                        answer:'lorem'
                    },
                    {
                        _id: ObjectId('61fd914d4a236b94f816c27d'),
                        question: 'lorem ipsum dolor set amet',
                        answer:'lorem'
                    }, {
                        _id: ObjectId('61fd914d4a236b94f816c27d'),
                        question: 'lorem ipsum dolor set amet',
                        answer: 'lorem'
                    }, {
                        _id: ObjectId('61fd914d4a236b94f816c27d'),
                        question: 'lorem ipsum dolor set amet',
                        answer: 'lorem'
                },
            ],
            quantity:2,
            product: {
                name:'lorem ipsum dolor set',
                image:'1452877_product.png',
                type:'immo file',
                price:20
            }
        }, {
            options:[
                {
                    _id: ObjectId('61fd914d4a236b94f816c27d'),
                    question: 'lorem ipsum dolor set amet',
                    answer: 'lorem'
                },
                {
                    _id: ObjectId('61fd914d4a236b94f816c27d'),
                    question: 'lorem ipsum dolor set amet',
                    answer:'lorem'
                }, {
                    _id: ObjectId('61fd914d4a236b94f816c27d'),
                    question: 'lorem ipsum dolor set amet',
                    answer: 'lorem'
                },
                {
                    _id: ObjectId('61fd914d4a236b94f816c27d'),
                    question: 'lorem ipsum dolor set amet',
                    answer: 'lorem'
                },
            ],
            quantity: 3,
            product: {
                name: 'lorem ipsum dolor set',
                image: '1452877_product.png',
                type: 'immo file',
                price: 20
            }
        }
    ]}

Hi @Ahmed_Abdelrahman,

This can be done by first $unwinding the orderItems array, using a $lookup against the products collection, replacing the product field then re-$grouping the results.

For example:

// setup
db.products.insert({
  _id: ObjectId('61c5e1e7c2ec39450cdf41b7'),
  name: 'lorem ipsum dolor set',
  image: '1452877_product.png',
  type: 'immo file',
  price: 20
});
db.orders.insertMany([{
  _id: ObjectId('61c45d25bdf9c1389879db9f'),
  orderItems: [{
    options: [{
      _id: ObjectId('61fd914d4a236b94f816c27d'),
      question: 'lorem ipsum dolor set amet',
      answer: 'lorem'
    }, {
      _id: ObjectId('61fd914d4a236b94f816c27d'),
      question: 'lorem ipsum dolor set amet',
      answer: 'lorem'
    }, {
      _id: ObjectId('61fd914d4a236b94f816c27d'),
      question: 'lorem ipsum dolor set amet',
      answer: 'lorem'
    }, {
      _id: ObjectId('61fd914d4a236b94f816c27d'),
      question: 'lorem ipsum dolor set amet',
      answer: 'lorem'
    }, ],
    quantity: 4,
    product: ObjectId('61c5e1e7c2ec39450cdf41b7')
  }, {
    options: [{
        _id: ObjectId('61fd914d4a236b94f816c27d'),
        question: 'lorem ipsum dolor set amet',
        answer: 'lorem'
      }, {
        _id: ObjectId('61fd914d4a236b94f816c27d'),
        question: 'lorem ipsum dolor set amet',
        answer: 'lorem'
      },
      {
        _id: ObjectId('61fd914d4a236b94f816c27d'),
        question: 'lorem ipsum dolor set amet',
        answer: 'lorem'
      }, {
        _id: ObjectId('61fd914d4a236b94f816c27d'),
        question: 'lorem ipsum dolor set amet',
        answer: 'lorem'
      },
    ],
    quantity: 3,
    product: ObjectId('61c5e1e7c2ec39450cdf41b7')
  }]
}])
// aggregate
db.orders.aggregate([
{ $unwind: "$orderItems" },
{ $lookup: {
   from: "products",
   localField: "orderItems.product",
   foreignField: "_id",
   as: "product"
}},
{ $set: {
  "orderItems.product": "$product"
}},
{ $group: {
  _id: "$_id",
  orderItems: { $push: "$orderItems" }
}}  
])

The above example is for the mongo/mongosh shell, but could be adapted to work in Node.js if it works for your use case.

thank you so mush this really works for me :grinning: :grinning:

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.