MongoDB Aggregate ObjectId внутри массива внедренных документов - PullRequest
1 голос
/ 24 января 2020

Я видел массу вопросов об агрегаторе $lookup для массивов ObjectIds, но я не могу ничего найти о том, когда ObjectId находится внутри массива встроенных документов.

У меня есть следуйте документу в базе данных mongodb:

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

Я хотел бы получить следующее:

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

Я пробовал следующее безуспешно:

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

Но это дает мне следующий результат:

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

1 Ответ

1 голос
/ 25 января 2020

Пожалуйста, попробуйте следующие запросы:

Если вы не хотите, чтобы объект, у которого нет совпадений в коллекции Gateway, существовал в массиве Alarms в конечном результате:

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' } } }
])

Тест: MongoDB-Playground

В противном случае, если вы хотите, чтобы все объекты в массиве Alarms возвращались независимо от того, есть ли совпадение в Gateway или нет:

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' } } }
])

Тест: MongoDB-Playground

Разница между двумя запросами будет одна, будет возвращаться ниже объекта в Alarms массив (Vs) один не делает.

{
    "Gateway": ObjectId("5e2b5425d02e05b6940de2fb"),
    "Port": 2
 }
...