执行条件查找,如果集合中没有数据,则添加自定义数据

Perform a conditional lookup, and add custom data if from collection has no data

我有两个合集

collection1 : [
 {
  _id:"90b992b7-b85f-4e1c-9080-fc3e2dba0db0",
  pIds: [ "47c9124d-f027-4221-8d60-9f491993d923", "08c89e83-ad62-443c-a731-3c6ccd9ca3af" ]
 }
]

collection2 : [
 {
  _id: "47d44016-ff84-44dc-b650-abab36d5f661",
  userId: "47c9124d-f027-4221-8d60-9f491993d923",
  isOnline: true
 }
]

collection2 有 "47c9124d-f027-4221-8d60-9f491993d923" 这个 userId 的数据,但是 collection2 没有 "08c89e83-ad62-443c-a731-3c6ccd9ca3af" 这个 userId 的数据。

现在想要像下面这样的输出

output : [
 {
  _id:"90b992b7-b85f-4e1c-9080-fc3e2dba0db0",
  pIds: [ 
   {
    userId: "47c9124d-f027-4221-8d60-9f491993d923",
    isOnline: true
   },
   {
    userId: "08c89e83-ad62-443c-a731-3c6ccd9ca3af",
    isOnline: false
   },
  ]
 }
]

尝试过

$lookup: {
 from: "collection2",
 let: { pIds: "$pIds" },
 pipeline: [
  { $match: { $expr: { $in: ["$userId", "$$pIds"] } } },
  { $project: { _id: 0 } },
 ],
 as: "pId",
}

任何解决方案都会有很大帮助....

提前致谢

db.collection1.aggregate([
  {
    "$unwind": "$pIds"
  },
  {
    "$lookup": {
      "from": "collection2",
      "localField": "pIds",
      "foreignField": "userId",
      "as": "docs"
    }
  },
  {
    "$group": {
      "_id": "$_id",
      "pids": {
        "$push": {
          userId: "$pIds",
          isOnline: { "$ifNull": [ { $first: "$docs.isOnline" }, false ] }
        }
      }
    }
  }
])

mongoplayground

这是另一种方法。我想知道接受的答案是否有任何改进。我想这归结为 "$unwind""$group""$map""$mergeObjects""$reduce""$filter" 的性能对比。我不确定如何衡量。

db.collection1.aggregate([
  {
    "$lookup": {
      "from": "collection2",
      "localField": "pIds",
      "foreignField": "userId",
      "as": "docs"
    }
  },
  {
    "$project": {
      "_id": 1,
      "pIds": {
        "$map": {
          "input": "$pIds",
          "as": "pId",
          "in": {
            "$mergeObjects": [
              { "userId": "$$pId" },
              { "isOnline": {
                  "$reduce": {
                    "input": "$docs",
                    "initialValue": false,
                    "in": {
                      "$or": [
                        false,
                        {
                          "$getField": {
                            "field": "isOnline",
                            "input": {
                              "$first": {
                                "$filter": {
                                  "input": "$docs",
                                  "as": "doc",
                                  "cond": { "$eq": [ "$$pId", "$$doc.userId" ] }
                                }
                              }
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      }
    }
  }
])

mongoplayground.net 上试用。