Home > Net >  Merge nested array data in single array and get them into root of document
Merge nested array data in single array and get them into root of document

Time:07-11

I am struggling with retrieving nested document in root.

below i have a schema inside it there is a array of tasks in which objects are present, in those objects there is again an array of assigned objects and in those objects i have solution array.

now i want to merge all solutions in one array and get that solution array in root od document.

Schema -

{
  _id: 1,
  tasks: [
    {
      _id: 1,
      assigned: [
        {
          _id: 1,
          solutions: [
            {
              _id: 1,
              name: 'solution 1',
            },
            {
              _id: 2,
              name: 'solution 2',
            },
          ],
        },
        {
          _id: 2,
          solutions: [
            {
              _id: 1,
              name: 'solution 1',
            },
            {
              _id: 2,
              name: 'solution 2',
            },
          ],
        },
      ],
    },
  ],
};

I want to merge all solutions to a single array based on some condition and set that array into new field in root of collection.

const order = this.orderModel
      .aggregate([
        { $match: { _id: orderId, student: studentId } },
        {
          $addFields: {
            solutions: {
              $map: {
                input: '$tasks.assigned.solutions',
                as: 's',
                in: '$$s',
              },
            },
          },
        },
      ])
      .exec();

output i am getting -

"solutions": [
        [
            [
                {
                    "id": 1,
                    "name": "solution 1",
                }
            ],
            [
                {
                    "_id": 2,
                    "name": "solution 2"
                }
            ]
        ]
    ],

CodePudding user response:

Maybe something like this:

db.collection.aggregate([
{
"$project": {
  "solutions": {
    "$reduce": {
      "input": "$tasks",
      "initialValue": [],
      "in": {
        "$concatArrays": [
          "$$value",
          {
            $reduce: {
              input: "$$this.assigned",
              initialValue: [],
              in: {
                $concatArrays: [
                  "$$value",
                  "$$this.solutions"
                ]
              }
            }
          }
        ]
       }
     }
   }
 }
}
])

Explained:

Use $project and two nested $reduce/$concatArrays to join the "solutions" array objects under the new array field "solutions" in the document root.

Playground

if you want to filter based on some condition you can replace "$$this.solutions" with:

          {
            $filter: {
              input: "$$this.solutions",
              cond: { $eq: ["$$this._id", 1] }
            }
          }

will filter only documents with _id:1

see example here

  • Related