Mongo $ lookup с несколькими условиями $ match или $ pipe - PullRequest
2 голосов
/ 24 мая 2019

У меня есть две коллекции монго, одна из которых содержит контакты, известные как пациенты, а другая содержит уведомления. Я пытаюсь вернуть результаты со статусом всех активных контактов: true в заданном branchId / clinic_id и включить их подтвержденные: ложные уведомления. Кроме того, я хочу убедиться, что контакты отображаются в результатах независимо от того, есть ли у них уведомления или нет.

Мне нужно «объединить» коллекции с помощью branchId aka clinic_id, а затем создать массив для каждого активного контакта с неподтвержденными уведомлениями.

Схема контакта:

{
  patientId: { type: String, required: true },
  clinic_id: { type: String, required: true },
  firstName: { type: String, uppercase: true, required: true },
  lastName: { type: String, uppercase: true, required: true },
  birthDate: { type: String },
  phone: { type: String, required: true },
  status: { type: Boolean, default: true }, // true - active patient
}

Схема уведомлений:

{
  branchId: { type: String, required: true }, // aka clinic_id
  patientId: { type: String, required: true },
  type: { type: String, required: true }, // sms, chat, system
  acknowledged: { type: Boolean, default: false },
  date: { type: Date, default: Date.now }
}

Запрос агрегации:

[
  {
    $match: { clinic_id: '2', status: { $eq: true } }
  },
  {
    $lookup: {
      from: 'notifications',
      let: { patient: '$patientId' },
      pipeline: [
        {
          $match: {
            $expr: {
              $and: [
                { $eq: ['$acknowleged', false] },
                { $eq: ['$patientId', '$$patientId'] }
              ]
            }
          }
        }
      ],
      as: 'notif'
    }
  }
]

НАСТОЛЬКО ДАЛЕЕ, ЧТОБЫ ПРЕДОСТАВИТЬ ЛУЧШИЕ РЕЗУЛЬТАТЫ - я использовал это, а затем фильтровал результаты в узле:

[ 
  { $match: { clinic_id: '2', status: { $eq: true } } },
  { "$lookup": {
    "from": "notifications",
    "let": { "patientId": "$patientId" },
    "pipeline": [
      { "$match": {
        "$expr": { "$eq": ["$branchId", "2"] },
        "acknowledged": { "$eq": false }
      }}
    ],
    "as": "notif"
  }}
]

Моя проблема в том, что я либо получаю правильные правильные контакты, но с записями в массиве уведомлений от пациентов с тем же Id пациента, но назначенным другому BranchId. Или, в зависимости от того, что я пробовал, я могу получить правильный массив уведомлений, но в начальном списке контактов будут отсутствовать записи. Каков наилучший способ получить нужный мне результат?

Пример вывода с комментариями по желаемому выводу и неверным выводом, который я испытал:

{
  patientId: 1,
  clinic_id: 100,
  firstName: 'John',
  lastName: 'Doe',
  birthDate: '2000-01-01',
  phone: '6665551212',
  status: true,
  notif: [
  {
    // This is correct
    branchId: 100, // branchId matches
    patientId: 1,  // patientId matches contacts patientId
    type: 'sms',
    acknowledged: false, // notification is unacknowledged
    date: '2019-05-18T16:18:05.480Z'
  },
  {
   // This is not correct
    branchId: 200, // branchId does not match contacts branchId
    patientId: 1,
    type: 'sms',
    acknowledged: true, // only want acknowledged: false
    date: '2019-05-20T16:18:05.480Z'
  },
  {
   // This is not correct
    branchId: 100, 
    patientId: 2, // PatientId does not match contact
    type: 'sms', 
    acknowledged: false,
    date: '2019-05-20T16:18:05.480Z'
  }
  ]
}

1 Ответ

2 голосов
/ 25 мая 2019

Вам необходимо добавить еще одно условие с помощью clinicId.Как то так

[
  { "$match": { "clinic_id": "2", "status": { "$eq": true }}},
  { "$lookup": {
    "from": "notifications",
    "let": { "patient": "$patientId", "clinic_id": "$clinic_id" },
    "pipeline": [
      { "$match": {
        "$expr": {
          "$and": [
            { "$eq": ["$patientId", "$$patientId"] },
            { "$eq": ["$branchId", "$$clinic_id"] }
          ]
        },
        "acknowleged": false
      }}
    ],
    "as": "notif"
  }}
]
...