Search code examples
javascriptmongodbmongoosemongoose-populate

How can I populate and then match based on the 'parent' id


I'm trying to "match" a referenced document (populated) with the parent document id. The goal is to only show members permissions for the specific organization and not all the other permissions they may have. So the 'entity.item', in this case an organization, would have to match the parent organization id. I'm trying to find out how, if possible, to access the parent organization id from a child doc.

let userId = '123';
let organizations = await Organization.find().where('members.includes(userId)').populate({
    path: 'members',
    options: { sort: { name: 1 } },
    populate: {
      path: 'permissions',
      match: {
        'entity.kind': 'Organization',
        'entity.item': organization._id  //HERE
      },
      populate: {
        path: 'entity.item'
      }
    }
  });

Solution

  • I ended up using the lookup operator on the aggregate method. Still testing use cases but seems to be working. The following answer pointed me in that direction.

    "With the mongodb 3.6 and above $lookup syntax it is quite simple to join nested fields without using $unwind."

    let organizations = await Organization.aggregate([
      { $sort: { name: 1 } },
      { $match: { $expr: { $in: [ user.id, '$members' ] } } },
      {
        $lookup: {
          from: 'user',
          let: { id: '$_id', members: '$members' },
          pipeline: [
            { $match: { $expr: { $in: [ '$_id', '$$members' ] } } },
            { $addFields: { id: '$_id' } },
            {
              $lookup: {
                from: 'permission',
                pipeline: [
                  { $match: { $expr: { $and: [
                    { $eq: [ '$entity.kind', 'Organization' ] },
                    { $eq: [ '$entity.item', '$$id' ] }
                  ] } } },
                  { $addFields: { id: '$_id' } },
                  {
                    $lookup: {
                      from: 'organization',
                      pipeline: [
                        { $match: { $expr: { $eq: [ '$_id', '$$id' ] } } },
                        { $addFields: { id: '$_id' } }
                      ],
                      as: 'entity.item'
                    }                      
                  }
                ],
                as: 'permissions'
              }
            }
          ],
          as: 'members'
        }
      },
      { $addFields: { id: '$_id' } }
    ]);