1

I have seen a ton of question about the $lookup aggregator for arrays of ObjectIds but I can't seem to find anything about when the ObjectId is inside an array of embedded documents.

I have the follow document inside a mongodb database:

_id: ObjectId('...')
Alarms: [
  {
    Gateway: ObjectId('...')
    Port: 1
  },
  {
    Gateway: ObjectId('...')
    Port: 2
  }
]

I would like to have the following:

_id: ObjectId('...')
Alarms [
  {
    Gateway: ...(Gateway Object),
    Port: 1
  },
  {
    Gateway: ...(Gateway Object),
    Port: 2
  }
]

I have tried the following with no success:

$lookup: {
  from: 'Gateway',
  localField: 'Alarms.Gateway',
  foreignField: '_id',
  as: 'Alarms.Gateway'
}

But this gives me the following result:

_id: ObjectId('...')
Alarms [
  {
    Gateway: {
      ...(Gateway Object)
    }
    Port: 1
  }
]
2
  • What happens if you've third object like { Gateway: ObjectId('...'), Port: 3 } in Alarms that doesn't have a matching doc in Gateway? Do you still want to keep that in Alarms array as is in final result or remove that & keep only the objects that have matches? Commented Jan 24, 2020 at 21:07
  • Change as: 'Alarms.Gateway' into as: 'Alarms' Commented Jan 24, 2020 at 21:23

1 Answer 1

1

Please try the below queries :

If you don't want the object which doesn't have match in Gateway collection exist in Alarms array in final result :

db.Alarms.aggregate([{ $unwind: '$Alarms' }, {
    $lookup: {
        from: 'Gateway',
        localField: 'Alarms.Gateway',
        foreignField: '_id',
        as: 'Alarms.Gateway'
    }
}, { $match: { 'Alarms.Gateway': { $ne: [] } } },
{ $addFields: { 'Alarms.Gateway': { $arrayElemAt: ['$Alarms.Gateway', 0] } } },
{ $group: { _id: '$_id', Alarms: { $push: '$Alarms' } } }
])

Test : MongoDB-Playground

Otherwise, if you want all objects in Alarms array to be returned irrespective of whether there is a match in Gateway or not :

db.Alarms.aggregate([{ $unwind: '$Alarms' }, {
    $lookup: {
        from: 'Gateway',
        localField: 'Alarms.Gateway',
        foreignField: '_id',
        as: 'Alarms.GatewayObj'
    }
}, { $addFields: { 'Alarms.Gateway': { $cond: [{ $ne: ['$Alarms.GatewayObj', []] }, { $arrayElemAt: ['$Alarms.GatewayObj', 0] }, '$Alarms.Gateway'] } } },
{ $project: { 'Alarms.GatewayObj': 0 } },
{ $group: { _id: '$_id', Alarms: { $push: '$Alarms' } } }
])

Test : MongoDB-Playground

Difference between two queries would be one will return below object in Alarms array (Vs) one don't.

{
    "Gateway": ObjectId("5e2b5425d02e05b6940de2fb"),
    "Port": 2
 }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.