MongoDB聚合框架通过id连接两个方面的集合

MongoDB聚合框架通过id连接两个方面的集合,mongodb,aggregation-framework,Mongodb,Aggregation Framework,我有以下文档(一个$facet的结果): 在上一篇文档中,我想使用MongoDb聚合框架构建一个集合,用productProperties丰富productRelations 这就是,我想为每个产品添加属性productProperty。请注意,该属性不仅添加到根元素中,还添加到每个相关产品中: [ { "productId": "1", "productProperty": "AAA", "relatedProducts": [ { "p

我有以下文档(一个
$facet
的结果):

在上一篇文档中,我想使用MongoDb聚合框架构建一个集合,用
productProperties
丰富
productRelations

这就是,我想为每个产品添加属性
productProperty
。请注意,该属性不仅添加到根元素中,还添加到每个相关产品中:

[
  {
    "productId": "1",
    "productProperty": "AAA",
    "relatedProducts": [
      {
        "productId": "2",
        "productProperty": "BBB",
        "relationProperty": 222
      },
      {
        "productId": "3",
        "productProperty": "CCC",      
        "relationProperty": 333
      }
    ]
  },
  {
    "productId": "2",
    "otherField": "BBB",
    "relatedProducts": [
      {
        "productId": "1",
        "productProperty": "AAA",
        "relationProperty": 111
      }
    ]
  }
]
我尝试使用
$lookup
,但它只适用于其他集合,我希望在原地进行聚合

提前谢谢

您可以运行嵌套以“连接”两个集合。问题是获取第一个元素及其子属性的语法有点麻烦,但您可以使用它作为一个大表达式运行。然后,您只需运行并获得预期结果:

db.collection.aggregate([
    {
        $project: {
            productRelations: {
                $map: {
                    input: "$productRelations",
                    as: "pr",
                    in: {
                        productId: "$$pr.productId",
                        productProperty: {
                            $let: {
                                vars: { 
                                    match: { 
                                        $arrayElemAt: [ { $filter: { input: "$productProperties", cond: { $eq: [ "$$pr.productId", "$$this.productId" ] } } }, 0 ] 
                                    } 
                                },
                                in: "$$match.productProperty"
                            }
                        },
                        relatedProducts: {
                            $map: {
                                input: "$$pr.relatedProducts",
                                as: "rp",
                                in: {
                                    productId: "$$rp.productId",
                                    relationProperty: "$$rp.relationProperty",
                                    productProperty: {
                                        $let: {
                                            vars: { 
                                                match: { 
                                                    $arrayElemAt: [ { $filter: { input: "$productProperties", cond: { $eq: [ "$$rp.productId", "$$this.productId" ] } } }, 0 ] 
                                                } 
                                            },
                                            in: "$$match.productProperty"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    {
        $unwind: "$productRelations"
    },
    {
        $replaceRoot: {
            newRoot: "$productRelations"
        }
    }
])

db.collection.aggregate([
    {
        $project: {
            productRelations: {
                $map: {
                    input: "$productRelations",
                    as: "pr",
                    in: {
                        productId: "$$pr.productId",
                        productProperty: {
                            $let: {
                                vars: { 
                                    match: { 
                                        $arrayElemAt: [ { $filter: { input: "$productProperties", cond: { $eq: [ "$$pr.productId", "$$this.productId" ] } } }, 0 ] 
                                    } 
                                },
                                in: "$$match.productProperty"
                            }
                        },
                        relatedProducts: {
                            $map: {
                                input: "$$pr.relatedProducts",
                                as: "rp",
                                in: {
                                    productId: "$$rp.productId",
                                    relationProperty: "$$rp.relationProperty",
                                    productProperty: {
                                        $let: {
                                            vars: { 
                                                match: { 
                                                    $arrayElemAt: [ { $filter: { input: "$productProperties", cond: { $eq: [ "$$rp.productId", "$$this.productId" ] } } }, 0 ] 
                                                } 
                                            },
                                            in: "$$match.productProperty"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    {
        $unwind: "$productRelations"
    },
    {
        $replaceRoot: {
            newRoot: "$productRelations"
        }
    }
])