programing

3레벨의 MongoDB 중첩 조회

shortcode 2023. 3. 5. 21:47
반응형

3레벨의 MongoDB 중첩 조회

데이터베이스에서 단일 개체 계층 전체를 JSON으로 가져와야 합니다.실제로, 이 결과를 달성하기 위한 다른 솔루션에 대한 제안은 매우 감사할 것입니다.MongoDB를 MongoDB와 함께 사용하기로 했습니다.$lookup지지하다.

세 가지 컬렉션이 있습니다.

파티

{ "_id" : "2", "name" : "party2" }
{ "_id" : "5", "name" : "party5" }
{ "_id" : "4", "name" : "party4" }
{ "_id" : "1", "name" : "party1" }
{ "_id" : "3", "name" : "party3" }    

주소.

{ "_id" : "a3", "street" : "Address3", "party_id" : "2" }
{ "_id" : "a6", "street" : "Address6", "party_id" : "5" }
{ "_id" : "a1", "street" : "Address1", "party_id" : "1" }
{ "_id" : "a5", "street" : "Address5", "party_id" : "5" }
{ "_id" : "a2", "street" : "Address2", "party_id" : "1" }
{ "_id" : "a4", "street" : "Address4", "party_id" : "3" }

어드레스 코멘트

{ "_id" : "ac2", "address_id" : "a1", "comment" : "Comment2" }
{ "_id" : "ac1", "address_id" : "a1", "comment" : "Comment1" }
{ "_id" : "ac5", "address_id" : "a5", "comment" : "Comment6" }
{ "_id" : "ac4", "address_id" : "a3", "comment" : "Comment4" }
{ "_id" : "ac3", "address_id" : "a2", "comment" : "Comment3" }

모든 상대방이 대응하는 주소를 가지고 있는 것을 모두 취득해, 기록의 일부로서 코멘트를 수신할 필요가 있습니다.나의 집약:

db.party.aggregate([{
    $lookup: {
        from: "address",
        localField: "_id",
        foreignField: "party_id",
        as: "address"
    }
},
{
    $unwind: "$address"
},
{
    $lookup: {
        from: "addressComment",
        localField: "address._id",
        foreignField: "address_id",
        as: "address.addressComment"
    }
}])

결과가 좀 이상해요.몇 가지 기록은 괜찮습니다.하지만 파티는_id: 4가 없습니다(주소는 없습니다).또, 2개의 파티가 있습니다._id: 1(다만, 주소가 다른 경우):

{
    "_id": "1",
    "name": "party1",
    "address": {
        "_id": "2",
        "street": "Address2",
        "party_id": "1",
        "addressComment": [{
            "_id": "3",
            "address_id": "2",
            "comment": "Comment3"
        }]
    }
}{
    "_id": "1",
    "name": "party1",
    "address": {
        "_id": "1",
        "street": "Address1",
        "party_id": "1",
        "addressComment": [{
            "_id": "1",
            "address_id": "1",
            "comment": "Comment1"
        },
        {
            "_id": "2",
            "address_id": "1",
            "comment": "Comment2"
        }]
    }
}{
    "_id": "3",
    "name": "party3",
    "address": {
        "_id": "4",
        "street": "Address4",
        "party_id": "3",
        "addressComment": []
    }
}{
    "_id": "5",
    "name": "party5",
    "address": {
        "_id": "5",
        "street": "Address5",
        "party_id": "5",
        "addressComment": [{
            "_id": "5",
            "address_id": "5",
            "comment": "Comment5"
        }]
    }
}{
    "_id": "2",
    "name": "party2",
    "address": {
        "_id": "3",
        "street": "Address3",
        "party_id": "2",
        "addressComment": [{
            "_id": "4",
            "address_id": "3",
            "comment": "Comment4"
        }]
    }
}

이것 좀 도와주세요.저는 MongoDB에 익숙하지 않지만 MongoDB는 제가 원하는 것을 할 수 있다고 생각합니다.

'문제'의 원인은 두 번째 집약 단계입니다.{ $unwind: "$address" }.이것에 의해, 와의 파티의 레코드가 삭제됩니다._id: 4(주소 배열이 비어있기 때문에) 통화 상대용으로 2개의 레코드를 생성합니다._id: 1그리고._id: 5(각각 2개의 주소가 있기 때문입니다).

  • 주소가 없는 통화자의 삭제를 방지하려면preserveNullAndEmptyArrays하기 위한 스테이지 옵션true.

  • 다른 주소에 대한 파티의 복제를 방지하려면 파이프라인에 집계 단계를 추가해야 합니다.또한 연산자와 함께 스테이지를 사용하여 출력에서 빈 주소 레코드를 제외합니다.

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] } }
    } 
  }
}]);

mongodb 3.6 이상의 구문에서는 를 사용하지 않고 네스트필드를 결합하는 것은 매우 간단합니다.

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" }
])

언급URL : https://stackoverflow.com/questions/36019713/mongodb-nested-lookup-with-3-levels

반응형