MongoDB 使用管道查找嵌套连接

MongoDB lookup with pipeline for nested joins

我有两个集合,我正在对其执行查找以获取组合数据。

公司:

{
  "_id": "638760ea-d109-49fd-8447-b52fe39227a3",
  "company": "test",
  "phones": [
    {
      "iso": "in",
      "number": "54666",
      "label": "CF_61a8c36b3368b0b21dbfbe3d"
    },
    {
      "iso": "hu",
      "number": "54433",
      "label": "CF_61a8c37d3368b0b21dbfbe3e"
    }
  ]
}

联系人标签:

{
  "_id": "096b0446-1099-49f4-87fc-21e583581780",
  "values": [
    {
      "id": "0a5c3f36-a06d-4f34-a1a9-9bbef7370940",
      "code": "CF_61a8c36b3368b0b21dbfbe3d",
      "value": "Personal"
    },
    {
      "id": "693574f9-cb30-48b1-9394-7673c9e71f33",
      "code": "CF_61a8c37d3368b0b21dbfbe3e",
      "value": "Home"
    }
  ]
}

我想要输出为

{
  "_id": "638760ea-d109-49fd-8447-b52fe39227a3",
  "company": "test",
  "phones": [
    {
      "iso": "in",
      "number": "54666",
      "label": "CF_61a8c36b3368b0b21dbfbe3d",
      "value": "Personal"
    },
    {
      "iso": "hu",
      "number": "54433",
      "label": "CF_61a8c37d3368b0b21dbfbe3e",
      "value": "Home"
    }
  ]
}

这是我为获得结果而应用的查询

{
  from: 'ContactLables',
  let:'ContactLablesCode':'$values.code',
  pipeline: [
      { "$match": {
        "$expr": { "$eq": [ "$phones.label", "$$ContactLablesCode" ] }
      }}
    ],
  as: 'phoneLables'
}

以上查询没有给我任何结果,对此有什么建议吗?

查询 1

  • 放松 phones
  • 使用管道查找但版本 MongoDB 5 我们有 localfield/foreighfield + 管道
  • localfield= the phones.labelforeign=array with the codes
  • if match => 数组有我们想要的标签,但我们不知道是哪个成员
  • 展开并匹配以仅保留 phone.label 的值,例如“Home”
  • 现在每个 phone 我们从另一个集合中得到它的值
  • 用 set/unset 修复结构(1 组和 "$$REMOVE" 也可以)
  • 最后分组并将 phone 推送给 _id 所有者

*为了加快速度,您需要 ContactLables.value 和 MongoDB 5 上的多键索引(此处查询是为了让 MongoDB 5 更快并使用 idenx)

Test code here

Company.aggregate(
[{"$unwind":"$phones"},
 {"$lookup":
  {"from":"ContactLables",
   "localField":"phones.label",
   "foreignField":"values.code",
   "pipeline":
   [{"$unwind":"$values"},
    {"$match":{"$expr":{"$eq":["$values.code", "$$label"]}}},
    {"$project":{"_id":0, "value":"$values.value"}}],
   "as":"results",
   "let":{"label":"$phones.label"}}},
 {"$set":{"phones.value":{"$first":"$results.value"}}},
 {"$unset":["results"]},
 {"$group":
  {"_id":"$_id",
   "company":{"$first":"$company"},
   "phones":{"$push":"$phones"}}}])

查询2

  • 同上,但管道内部使用reduce代替unwind和match
  • reduce 以查找匹配的成员,并保留其值,例如“Home”

Test code here

Company.aggregate(
[{"$unwind":"$phones"},
 {"$lookup":
  {"from":"ContactLables",
   "localField":"phones.label",
   "foreignField":"values.code",
   "pipeline":
   [{"$project":
     {"_id":0,
      "value":
      {"$reduce":
       {"input":"$values",
        "initialValue":null,
        "in":
        {"$let":
         {"vars":{"v":"$$value"},
          "in":
          {"$cond":
           [{"$eq":["$$this.code", "$$label"]}, "$$this.value",
            "$$v"]}}}}}}}],
   "as":"results",
   "let":{"label":"$phones.label"}}},
 {"$set":{"phones.value":{"$first":"$results.value"}}},
 {"$unset":["results"]},
 {"$group":
  {"_id":"$_id",
   "company":{"$first":"$company"},
   "phones":{"$push":"$phones"}}}])