MongoDB nested lookup with 3 levels

前端 未结 2 1408
粉色の甜心
粉色の甜心 2020-12-01 00:02

I need to retrieve the entire single object hierarchy from the database as a JSON. Actually the proposal about any other solution to achive this result would be highly appri

相关标签:
2条回答
  • 2020-12-01 00:39

    With the mongodb 3.6 and above $lookup syntax it is quite simple to join nested fields without using $unwind.

    db.party.aggregate([
      { "$lookup": {
        "from": "address",
        "let": { "partyId": "$_id" },
        "pipeline": [
          { "$match": { "$expr": { "$eq": ["$party_id", "$$partyId"] }}},
          { "$lookup": {
            "from": "addressComment",
            "let": { "addressId": "$_id" },
            "pipeline": [
              { "$match": { "$expr": { "$eq": ["$address_id", "$$addressId"] }}}
            ],
            "as": "address"
          }}
        ],
        "as": "address"
      }},
      { "$unwind": "$address" }
    ])
    
    0 讨论(0)
  • 2020-12-01 00:51

    The cause of your 'troubles' is the second aggregation stage - { $unwind: "$address" }. It removes record for party with _id: 4 (because its address array is empty, as you mention) and produces two records for parties _id: 1 and _id: 5 (because each of them has two addresses).

    • To prevent removing of parties without addresses you should set preserveNullAndEmptyArrays option of $unwind stage to true.

    • To prevent duplicating of parties for its different addresses you should add $group aggregation stage to your pipeline. Also, use $project stage with $filter operator to exclude empty address records in output.

    db.party.aggregate([{
      $lookup: {
        from: "address",
        localField: "_id",
        foreignField: "party_id",
        as: "address"
      }
    }, {
      $unwind: {
        path: "$address",
        preserveNullAndEmptyArrays: true
      }
    }, {
      $lookup: {
        from: "addressComment",
        localField: "address._id",
        foreignField: "address_id",
        as: "address.addressComment",
      }
    }, {
      $group: {
        _id : "$_id",
        name: { $first: "$name" },
        address: { $push: "$address" }
      }
    }, {
      $project: {
        _id: 1,
        name: 1,
        address: {
          $filter: { input: "$address", as: "a", cond: { $ifNull: ["$$a._id", false] } }
        } 
      }
    }]);
    
    0 讨论(0)
提交回复
热议问题