【问题标题】:How to lookup inside lookup in MongoDB Aggregate?如何在 MongoDB Aggregate 中查找内部查找?
【发布时间】:2021-02-24 12:25:51
【问题描述】:

我有一个简单的 3 个集合。下面是他们的伪代码。我想获得所有货物,对于每批货物,我想获得该货物的所有出价,并且在每次出价中,我都需要 userDetails 对象。

User: {
  name: string,
}

Shipment: {
  from: string,
  to: string
}

Bid: {
  amount: number,
  shipmentId: Ref_to_Shipment
  userId: Ref_to_User
}

这是我尝试过的:

const shipments = await ShipmentModel.aggregate([
            {
                $lookup: {
                    from: "bids",
                    localField: "_id",
                    foreignField: "shipmentId",
                    as: "bids"
                }
            },
            {
                $lookup: {
                    from: "users",
                    localField: "bids.userId",
                    foreignField: "_id",
                    as: "bids.user"
                }
            }
        ])

我得到了以下结果:

[
    {
        "_id": "5fad2fc04458ac156531d1b1",
        "from": "Belgrade",
        "to": "London",
        "__v": 0,
        "bids": {
            "user": [
                {
                    "_id": "5fad2cdb4d19c80d1b6abcb7",
                    "name": "Amel",
                    "email": "Muminovic",
                    "password": "d2d2d2",
                    "__v": 0
                }
            ]
        }
    }
]

我正在尝试获取所有货件及其出价和出价内的用户。 数据应如下所示

[
    {
        "_id": "5fad2fc04458ac156531d1b1",
        "from": "Belgrade",
        "to": "London",
        "__v": 0,
        "bids": [
            {
                "_id": "5fad341887c2ae1feff73402",
                "amount": 400,
                "userId": "5fad2cdb4d19c80d1b6abcb7",
                "shipmentId": "5fad2fc04458ac156531d1b1",
                "user": {
                    "name": "Amel",
                }
                "__v": 0
            }
        ]
    }
]

【问题讨论】:

    标签: node.js database mongodb mongoose


    【解决方案1】:

    试试下面的代码:

    const shipments = await ShipmentModel.aggregate([
                {
                    $lookup: {
                        from: "bids",
                        localField: "_id",
                        foreignField: "shipmentId",
                        as: "bids"
                    }
                },
                {
                  $unwind: {
                    path: "$bids",
                    preserveNullAndEmptyArrays: true
                  }
                },
                {
                    $lookup: {
                        from: "users",
                        localField: "bids.userId",
                        foreignField: "_id",
                        as: "bids.user"
                    }
                }
            ])
    

    如果你想防止 null 和空数组然后设置

    preserveNullAndEmptyArrays: false
    

    【讨论】:

    • 这样我就可以为每个未平仓出价获得发货。我可以在一个 Shipment 中有 10 个投标,所以我将得到 10 个以投标作为对象而不是数组的货件?
    【解决方案2】:

    尝试this 查询并检查是否有效并且行为是否符合您的预期:

    db.Shipment.aggregate([
      {
        $lookup: {
          from: "Bid",
          localField: "id",
          foreignField: "shipmentId",
          as: "bids"
        }
      },
      {
        $lookup: {
          from: "user",
          localField: "id",
          foreignField: "id",
          as: "newBids"
        }
      },
      {
        $project: {
          "newBids.id": 0,
          "newBids._id": 0,
          
        }
      },
      {
        $match: {
          "bids.userId": 1
        }
      },
      {
        $addFields: {
          "newBids": {
            "$arrayElemAt": [
              "$newBids",
              0
            ]
          }
        }
      },
      {
        $set: {
          "bids.user": "$newBids"
        }
      },
      {
        $project: {
          "newBids": 0
        }
      }
    ])
    

    此查询执行您的双重$lookup,然后执行$project 以删除您不需要的字段,并查找userId 以添加字段user。由于$lookup 生成一个数组,所以必须使用arrayElemAt 来获取第一个位置。

    然后将$set这个值生成到对象中作为bids.user并删除旧值。

    请注意,我使用了一个新字段 id 而不是 _id 来更轻松地读取数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-04
      • 2020-11-20
      • 1970-01-01
      • 2018-02-09
      • 1970-01-01
      • 2020-06-07
      • 2023-03-09
      相关资源
      最近更新 更多