You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过MongoDB聚合将数组中rentalContractId关联至详情表

MongoDB数组内关联查询的正确实现方式

问题场景

需要从rentalcontractdetails集合中查询product文档里productPrice数组中每个对象的rentalContractId对应的详情数据。

product文档结构:

{
  "productPrice": [
    {
      "rentalContractId": ObjectId("64018dfc8a7d37f378d6c427"),
      "price": 20
    },
    {
      "rentalContractId": ObjectId("64018dfc8a7d37f378d6c426"),
      "price": 10
    }
  ]
}

错误尝试及问题

使用以下聚合语句时,每个productPrice对象都会包含所有关联的rentalcontractdetails数据,不符合预期:

db.products.aggregate([
{
      $lookup: {
        from: "rentalcontractdetails",
        localField: "productPrice.rentalContractId",
        foreignField: "_id",
        as: "rentalContract",
      },
    }, { $set: {
      "productPrice.rentalContract": "$rentalContract"
    }}])

错误输出示例:

[
                    {
                        "rentalContractId": "64018dfc8a7d37f378d6c427",
                        "price": 20,
                        "rentalContract": [
                            {
                                "_id": "64018dfc8a7d37f378d6c427",
                                "contractType": "8 - Days Rental",
                                "contractDaysInNumber": 8,
                                "createdAt": "2023-03-03T06:04:44.531Z",
                                "isDeleted": false,
                                "isArchived": false
                            },
                            {
                                "_id": "64018dfc8a7d37f378d6c426",
                                "contractType": "4 - Days Rental",
                                "contractDaysInNumber": 4,
                                "createdAt": "2023-03-03T06:04:44.531Z",
                                "isDeleted": false,
                                "isArchived": false
                            }
                        ]
                    },
                    {
                        "rentalContractId": "64018dfc8a7d37f378d6c426",
                        "price": 10,
                        "rentalContract": [
                            {
                                "_id": "64018dfc8a7d37f378d6c427",
                                "contractType": "8 - Days Rental",
                                "contractDaysInNumber": 8,
                                "createdAt": "2023-03-03T06:04:44.531Z",
                                "isDeleted": false,
                                "isArchived": false
                            },
                            {
                                "_id": "64018dfc8a7d37f378d6c426",
                                "contractType": "4 - Days Rental",
                                "contractDaysInNumber": 4,
                                "createdAt": "2023-03-03T06:04:44.531Z",
                                "isDeleted": false,
                                "isArchived": false
                            }
                        ]
                    }
                ]

期望输出

将每个rentalContractId替换为对应的详情数据:

{
  "productPrice": [
    {
      "rentalContractId": {
          "_id": "64018dfc8a7d37f378d6c427",
          "contractType": "8 - Days Rental",
        },
      "price": 20
    },
    {
      "rentalContractId": {
          "_id": "64018dfc8a7d37f378d6c426",
          "contractType": "4 - Days Rental",
        },
      "price": 10
    }
  ]
}

解决方案

需要先拆分productPrice数组,再逐个关联,最后重组数组。正确的聚合语句如下:

db.products.aggregate([
  // 拆分productPrice数组为单个文档
  { $unwind: "$productPrice" },
  // 关联rentalcontractdetails集合,匹配对应的_id
  {
    $lookup: {
      from: "rentalcontractdetails",
      localField: "productPrice.rentalContractId",
      foreignField: "_id",
      as: "productPrice.rentalContractId"
    }
  },
  // 将关联后的数组转为单个对象(因为lookup返回数组,这里取第一个元素)
  {
    $set: {
      "productPrice.rentalContractId": { $first: "$productPrice.rentalContractId" }
    }
  },
  // 重新组合productPrice数组
  { $group: {
      _id: "$_id",
      productPrice: { $push: "$productPrice" },
      // 如果需要保留其他字段,在这里添加,比如:
      // otherField: { $first: "$otherField" }
    }
  }
])

代码说明

  1. $unwind:将productPrice数组拆分为独立的文档,每个文档对应数组中的一个元素,确保后续的$lookup可以逐个匹配。
  2. $lookup:此时localField指向单个productPrice.rentalContractId,关联后会将匹配的详情存入productPrice.rentalContractId数组。
  3. $set + $first:因为$lookup返回的是数组(即使只有一个匹配项),用$first取出数组中的第一个元素,替换原来的rentalContractId值。
  4. $group:将拆分后的文档重新组合为原结构,把每个productPrice元素推回数组,同时保留原文档的_id和其他需要的字段。

内容的提问来源于stack exchange,提问作者Nick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 02:12:41