【问题标题】:Mongo $lookup with multiple $match or $pipeline conditions具有多个 $match 或 $pipeline 条件的 Mongo $lookup
【发布时间】:2019-10-11 11:02:26
【问题描述】:

我有两个 mongo 集合,一个包含联系人,即患者,另一个包含通知。我正在尝试在给定的 branchId / Clinic_id 中返回所有活动联系人状态的结果:true 并包括他们的确认:错误通知。另外,我想确保联系人显示在结果中,无论他们是否有通知。

我需要通过 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"
  }}
]

我的问题是我要么得到正确的联系人,但在 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'
  }
  ]
}

【问题讨论】:

  • 如果有人通过原始聚合查询有轻微的拼写错误来跟踪问题。 “承认”当然应该是“承认”。我编辑的字符不够_

标签: javascript node.js mongodb mongoose aggregation-framework


【解决方案1】:

您需要使用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"
  }}
]

【讨论】:

  • 谢谢。我不得不在 let 中将患者更改为 patientId,然后在 match 和 expr 中使用变量 branchId 而不是 $$clinic_id 并且它起作用了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-12
  • 2019-10-11
  • 1970-01-01
  • 1970-01-01
  • 2019-10-09
  • 1970-01-01
  • 2019-11-07
相关资源
最近更新 更多