Aggregate with multiple lookup and pipeline return only the last element

Viewed 155

I try below code, it's working to lookup value from other collection. But why it only return the last element.

If I omitted the unwind function, It does return all result from the model, but the second lookup will not working as the first lookup return arrays.

My objective is to look up folder that include the model id which represented in templatefolders collection.

const result = await this.dashboardModel
      .aggregate([{ $match: filter }])
      .lookup({
        from: 'templatefolders',
        as: 'template',
        let: { id: '$_id' },
        pipeline: [
          {
            $match: {
              $expr: {
                $and: [
                  {
                    $eq: ['$dashboardId', '$$id'],
                  },
                  {
                    $eq: ['$deletedAt', null],
                  },
                ],
              },
            },
          },
          {
            $project: {
              _id: 1,
              folderId: 1,
            },
          },
        ],
      })
      .unwind('template')
      .lookup({
        from: 'folders',
        as: 'folder',
        let: { folderId: '$template.folderId' },
        pipeline: [
          {
            $match: {
              $expr: {
                $and: [
                  {
                    $eq: ['$_id', '$$folderId'],
                  },
                  {
                    $eq: ['$deletedAt', null],
                  },
                ],
              },
            },
          },
          {
            $project: {
              _id: 1,
              name: 1,
            },
          },
        ],
      })
      .unwind('folder')
      .exec();
    return result;

Result

{
  "data": [
    {
      ...(parent field)
      "template": {
        "_id": "60ab22b03b39e40012b7cc4a",
        "folderId": "60ab080b3b39e40012b7cc41"
      },
      "folder": {
        "_id": "60ab080b3b39e40012b7cc41",
        "name": "Folder 1"
      }
    }
  ],
  "meta": {},
  "success": true,
  "message": "Succesfully get list"
}

I came from Front end background. I hope my question is not a silly one.

Thanks!

EDIT:

dashboard: [{
  _id: dashboard1
}]

templatefolders: [{
  dashboardId: dashboard1,
  folderId: folder123
}]

folders: [{
  _id: folder123
}]
1 Answers

You can use $lookup to join collections

  • $lookup to join two collections .Lookup doc
  • $unwind to deconstruct the array. Unwind doc
  • $group to reconstruct the array which we already deconstructed Group doc

Here is the code

db.dashboard.aggregate([
  {
    "$lookup": {
      "from": "templatefolders",
      "localField": "_id",
      "foreignField": "dashboardId",
      "as": "joinDashboard"
    }
  },
  {
    "$unwind": "$joinDashboard"
  },
  {
    "$lookup": {
      "from": "folders",
      "localField": "joinDashboard.folderId",
      "foreignField": "_id",
      "as": "joinDashboard.joinFolder"
    }
  },
  {
    "$group": {
      "_id": "$_id",
      "joinDashboard": {
        "$push": "$joinDashboard"
      }
    }
  }
])

Working Mongo playground

Related