链接在另一文档的阵列与文档到相应的元件在阵列中的每个元件的MongoDB

问题描述 投票:1回答:1

使用MongoDB 4.2和MongoDB Atlas来测试聚合管道。

我有这个products集合,其中包含具有以下架构的文档:

 {
    "name": "TestProduct",
    "relatedList": [
      ObjectId("someId"),
      ObjectId("anotherId")
    ]
 }

然后有这个cities集合,其中包含具有此架构的文档:

{
        "name": "TestCity",
        "instructionList": [
          { related_id: ObjectId("anotherId"), foo: bar},
          { related_id: ObjectId("someId"), foo: bar}
          { related_id: ObjectId("notUsefulId"), foo: bar}
          ...
        ]
 }

我的目标是将两个集合都连接起来以输出类似的内容(该操作是从城市文档的指令列表中选择每个相关对象,然后将其放入产品文档的相关列表中:

]
{
        "name": "TestProduct",
        "relatedList": [
          { related_id: ObjectId("someId"), foo: bar},
          { related_id: ObjectId("anotherId"), foo: bar},
        ]
}

我尝试使用$查找操作者的聚集等this

$lookup:{
  from: 'cities',
  let: {rId:'$relatedList._id'},
  pipeline: [
         {
           $match: {
             $expr: {
               $eq: ["$instructionList.related_id", "$$rId"]
             }
           }
         },
  ]
}

但是它不起作用,这种复杂的管道语法让我有些迷茫。

mongodb pipeline bson
1个回答
0
投票

我相信您只需要$ unwind数组以查找该关系,然后$ group重新收集它们。也许像这样:

.aggregeate([
    {$unwind:"relatedList"},
    {$lookup:{
         from:"cities",
         let:{rId:"$relatedList.id"}
         pipeline:[
             {$match:{$expr:{$eq:["$instructionList.related_id", "$$rId"]}}},
             {$unwind:"$instructionList"},
             {$match:{$expr:{$eq:["$instructionList.related_id", "$$rId"]}}},
             {$project:{_id:0, instruction:"$instructionList"}}
         ],
         as: "lookedup"
     }},
     {$addFields: {"relatedList.foo":"$lookedup.0.instruction.foo"}},
     {$group: {
                _id:"$_id",
                root: {$first:"$$ROOT"},
                relatedList:{$push:"$relatedList"}
     }},
     {$addFields:{"root.relatedList":"$relatedList"}},
     {$replaceRoot:{newRoot:"$root"}}
])

关于每个阶段的一点:

  • $ unwind为数组的每个元素复制整个文档,用单个元素替换数组
  • $ lookup然后可以分别考虑每个元素。 $ lookup.pipeline中的阶段:一种。 $ match,因此我们只展开具有匹配ID的文档b。 $展开数组,以便我们考虑单个元素C。重复$ match,所以我们只剩下匹配的元素(希望只有1个)
  • $ addFields将从查找中检索到的foo字段分配给从relatedList中的对象
  • $ group将具有相同_id的所有文档(即从单个原始文档解卷的文档)收集在一起,将第一个存储为'root',并将所有relatedList元素推回数组中]
  • $ addFields将relatedList移入根目录
  • $ replaceRoot返回root,它现在应该是原始文档,并将匹配的foo添加到每个relatedList元素中
© www.soinside.com 2019 - 2024. All rights reserved.