복붙노트

[MONGODB] MongoDB를 3 레벨 룩업 중첩

MONGODB

MongoDB를 3 레벨 룩업 중첩

나는 JSON으로 데이터베이스 전체를 하나의 객체 계층 구조를 검색해야합니다. 실제로이 결과를 실현하려 다른 솔루션에 대한 제안은 매우 appriciated 될 것이다. 나는 그것의 $ 조회를 지원하여 MongoDB를 사용하기로 결정했다.

나는 3 개 컬렉션이 그래서 :

파티

{ "_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" }

addressComment

{ "_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가 누락로 (그것을 위해 주소가 없음). 또한 두 당사자는 (하지만 서로 다른 주소) 결과 집합의 1이 _ID 있습니다 :

{
    "_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를 꽤 새로운 해요 그러나 나는 내가 그것에서 무엇을해야 할 수 있습니다 생각합니다.

해결법

  1. ==============================

    1.당신의 '문제'의 원인은 두 번째 집계 단계입니다 - {$ 언 와인드 : "$ 주소"}. 그것은 _id 파티에 대한 기록을 제거 : 4 (해당 주소의 배열이 당신이 언급으로, 비어 있기 때문에) 파티에 대한 두 개의 레코드가 _ID 생산 : 1 및 _ID : 5 (그들 각각 두 개의 주소를 가지고 있기 때문에).

    당신의 '문제'의 원인은 두 번째 집계 단계입니다 - {$ 언 와인드 : "$ 주소"}. 그것은 _id 파티에 대한 기록을 제거 : 4 (해당 주소의 배열이 당신이 언급으로, 비어 있기 때문에) 파티에 대한 두 개의 레코드가 _ID 생산 : 1 및 _ID : 5 (그들 각각 두 개의 주소를 가지고 있기 때문에).

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

    2.$ 조회 구문 MongoDB를 3.6 이상이 $ 언 와인드를 사용하지 않고 중첩 된 필드에 가입하는 것은 매우 간단합니다.

    $ 조회 구문 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" }
    ])
    
  3. from https://stackoverflow.com/questions/36019713/mongodb-nested-lookup-with-3-levels by cc-by-sa and MIT license