Search code examples
mongodbmongodb-queryaggregate

How do I use $addToSet with condition in group?


I have the following documents:

_id: ObjectId('641316fd596514e63a2121ca'),
orgId: 3,
devices {
    _id: ObjectId('64131139596514e63a2121c1')
    name: 'Device A'
}

_id: ObjectId('641316fd596514e63a2121ca'),
orgId: 3

_id: ObjectId('64131b2b596514e63a2121ce'),
orgId: 4,
devices {
    _id: ObjectId('64131c1e596514e63a2121d0')
    name: 'Device B'
}

_id: ObjectId('64131d38596514e63a2121d1'),
orgId: 5

_id: ObjectId('64131d38596514e63a2121d1'),
orgId: 5

From here I'm trying to group these documents by _id and orgId, and in that process add a new array of objects called "endpoints" that contains type: 'linux' and refId: '$devices._id'. But such object should ONLY be added to the array if the document has a devices field.

Like this:

_id: {
    id: ObjectId('641316fd596514e63a2121ca'),
    orgId: 3
},
endpoints: [
    type: 'windows',
    refId: ObjectId('64131139596514e63a2121c1')
]

_id: {
    id: ObjectId('64131b2b596514e63a2121ce'),
    orgId: 4
},
endpoints: [
    type: 'windows',
    refId: ObjectId('64131c1e596514e63a2121d0')
]

_id: {
    id: ObjectId('64131d38596514e63a2121d1'),
    orgId: 5
},
endpoints: [
]

This is what I've tried:

{
  $group: {
    _id: {
      id: '$_id',
      orgId: '$orgId',
    },
    endpoints: { 
      $addToSet: {
        $cond: {
          if: { 
            $ne: [ '$devices', undefined ] 
          },
          then: { 
            type: 'linux',
            refId: '$devices._id'
          },
          else: '$$REMOVE'
        }
      }
    }
  }
}

However I still get objects without "refId". like this:

_id: {
    id: ObjectId('64131d38596514e63a2121d1'),
    orgId: 5
},
endpoints: [
    {
        type: 'linux'
    }
]

Solution

  • Try this:

    • $eq with $type: To check if the devices.name property is of type string. If the devices property does not exist, it will resolve to false.
    $addToSet: {
      $cond: {
        if: { 
          $eq: [{ $type: '$devices.name' }, 'string'],
        },
        then: { 
          type: 'linux',
          refId: '$devices._id'
        },
        else: '$$REMOVE'
      }
    }