在嵌入式文档数组中查找引用文档

Lookup for a referenced document in an array of embedded documents

我有两个 collection。 一个包含 objects 的数组。这些 objects 拥有一个字段,该字段的 ID 指向另一个 collection 中的文档。 目标是 "replace" 文档的引用。听起来很简单,但我不知道如何存档。

例如

Collection"Product"

{ "_id": 1,
  "alias": "ProductA"
},
{ "_id": 2,
  "alias": "ProductC"
}

Collection "Order"

{ "_id": 5765,
  "cart": [
    {
      "product": 1,
      "qty": 7
    }, {
      "product": 2,
      "qty": 6
    }
  ]
}

我需要查询的是:

{ "_id": 5765,
  "cart": [
    {
      "product": {
        "_id": 1,
        "alias": "ProductA"
      },
      "qty": 7
    }, {
      "product": {
        "_id": 2,
        "alias": "ProductC"
      },
      "qty": 6
    }
  ]
}

我尝试了一个简单的查找,但数组将只包含产品。我需要更改什么?

{
    $lookup: {
        from: "products",
        let: {
            tmp: "$cart.product"
        },
        pipeline: [
            {
                $match: {
                    $expr: {
                        $in: ["$_id", "$$tmp"]
                    }
                }
            }
        ],
        as: "cart.product"
    }
}

感谢您的帮助。

我添加了一个新的 $addFields 阶段来转换 $lookup 阶段的输出 - 它获得了所需的输出:

db.order.aggregate([
{
    $lookup: {
        from: "product",
        let: {
            tmp: "$cart.product"
        },
        pipeline: [
            {
                $match: {
                    $expr: {
                        $in: ["$_id", "$$tmp"]
                    }
                }
            }
        ],
        as: "products"
    }
},
{ 
    $addFields: {
         cart: {
             $map: {
                 input: "$cart", as: "ct",
                 in: {
                     product: {
                         $arrayElemAt: [ 
                             { $filter: {
                                   input: "$products", as: "pr",
                                   cond: {
                                      $eq: [ "$$ct.product", "$$pr._id" ]
                                   }
                              }
                          }, 0 ]
                     },
                     qty: "$$ct.qty"
                 }
             }
         }
    }
}
] ).pretty()