1

나는이 형식으로 데이터를 가져 오는 집계에서 하나의 결과를 얻은 상황이 있습니다.다른 배열의 일치하는 두 객체를 하나의 객체로 병합하는 방법은 무엇입니까?

{ 
    "_id" : ObjectId("5a42432d69cbfed9a410e8ad"), 
    "bacId" : "BAC0023444", 
    "cardId" : "2", 
    "defaultCardOrder" : "2", 
    "alias" : "Finance", 
    "label" : "Finance", 
    "for" : "", 
    "cardTooltip" : { 
     "enable" : true, 
     "text" : "" 
    }, 
    "dataBlocks" : [ 
     { 
      "defaultBlockOrder" : "1", 
      "blockId" : "1", 
      "data" : "0" 
     }, 
     { 
      "defaultBlockOrder" : "2", 
      "blockId" : "2", 
      "data" : "0" 
     }, 
     { 
      "defaultBlockOrder" : "3", 
      "blockId" : "3", 
      "data" : "0" 
     } 
    ], 
    "templateBlocks" : [ 
     { 
      "blockId" : "1", 
      "label" : "Gross Profit", 
      "quarter" : "", 
      "data" : "", 
      "dataType" : { 
       "typeId" : "2" 
      }, 
      "tooltip" : { 
       "enable" : true, 
       "text" : "" 
      } 
     }, 
     { 
      "blockId" : "2", 
      "label" : "Profit Forecast", 
      "quarter" : "", 
      "data" : "", 
      "dataType" : { 
       "typeId" : "2" 
      }, 
      "tooltip" : { 
       "enable" : true, 
       "text" : "" 
      } 
     }, 
     { 
      "blockId" : "3", 
      "label" : "Resource Billing", 
      "quarter" : "", 
      "data" : "", 
      "dataType" : { 
       "typeId" : "2" 
      }, 
      "tooltip" : { 
       "enable" : true, 
       "text" : "" 
      } 
     } 
    ] 
}, 
{ 
    "_id" : ObjectId("5a42432d69cbfed9a410e8ad"), 
    "bacId" : "BAC0023444", 
    "cardId" : "3", 
    "defaultCardOrder" : "3", 
    "alias" : "Staffing", 
    "label" : "Staffing", 
    "for" : "", 
    "cardTooltip" : { 
     "enable" : true, 
     "text" : "" 
    }, 
    "dataBlocks" : [ 
     { 
      "defaultBlockOrder" : "1", 
      "blockId" : "1", 
      "data" : "1212" 
     }, 
     { 
      "defaultBlockOrder" : "2", 
      "blockId" : "2", 
      "data" : "1120" 
     }, 
     { 
      "defaultBlockOrder" : "3", 
      "blockId" : "3", 
      "data" : "1200" 
     } 
    ], 
    "templateBlocks" : [ 
     { 
      "blockId" : "1", 
      "label" : "Staffing Planner", 
      "quarter" : "", 
      "data" : "", 
      "dataType" : { 
       "typeId" : "1" 
      }, 
      "tooltip" : { 
       "enable" : true, 
       "text" : "" 
      } 
     }, 
     { 
      "blockId" : "2", 
      "label" : "Baseline", 
      "quarter" : "", 
      "data" : "", 
      "dataType" : { 
       "typeId" : "1" 
      }, 
      "tooltip" : { 
       "enable" : true, 
       "text" : "" 
      } 
     }, 
     { 
      "blockId" : "3", 
      "label" : "Projected", 
      "quarter" : "", 
      "data" : "", 
      "dataType" : { 
       "typeId" : "1" 
      }, 
      "tooltip" : { 
       "enable" : true, 
       "text" : "" 
      } 
     } 
    ] 
} 

는 지금은 "BLOCKID"의 기반으로 "블럭 (datablocks)"와 "templateBlocks"이 경우에는 여기에, 각 행에 대해 객체의 두 배열을 비교하려면 나는 다음과 같은 형식의 결과를 얻으려면 .

{ 
    "_id" : ObjectId("5a42432d69cbfed9a410e8ad"), 
    "bacId" : "BAC0023444", 
    "cardId" : "2", 
    "defaultCardOrder" : "2", 
    "alias" : "Finance", 
    "label" : "Finance", 
    "for" : "", 
    "cardTooltip" : { 
     "enable" : true, 
     "text" : "" 
    }, 
    "blocks" : [ 
     { 
      "defaultBlockOrder" : "1", 
      "blockId" : "1", 
      "data" : "0", 
      "label" : "Gross Profit", 
      "quarter" : "", 
      "dataType" : { 
       "typeId" : "2" 
      }, 
      "tooltip" : { 
       "enable" : true, 
       "text" : "" 
      } 
     }, 
     { 
      "defaultBlockOrder" : "2", 
      "blockId" : "2", 
      "data" : "0", 
      "label" : "Profit Forecast", 
      "quarter" : "", 
      "dataType" : { 
       "typeId" : "2" 
      }, 
      "tooltip" : { 
       "enable" : true, 
       "text" : "" 
      } 
     }, 
     { 
      "defaultBlockOrder" : "3", 
      "blockId" : "3", 
      "data" : "0", 
      "label" : "Resource Billing", 
      "quarter" : "", 
      "dataType" : { 
       "typeId" : "2" 
      }, 
      "tooltip" : { 
       "enable" : true, 
       "text" : "" 
      } 
     } 
    ] 
}, 
{ 
    "_id" : ObjectId("5a42432d69cbfed9a410e8ad"), 
    "bacId" : "BAC0023444", 
    "cardId" : "3", 
    "defaultCardOrder" : "3", 
    "alias" : "Staffing", 
    "label" : "Staffing", 
    "for" : "", 
    "cardTooltip" : { 
     "enable" : true, 
     "text" : "" 
    }, 
    "dataBlocks" : [ 
     { 
      "defaultBlockOrder" : "1", 
      "blockId" : "1", 
      "data" : "1212", 
      "label" : "Staffing Planner", 
      "quarter" : "", 
      "dataType" : { 
       "typeId" : "1" 
      }, 
      "tooltip" : { 
       "enable" : true, 
       "text" : "" 
      } 
     }, 
     { 
      "defaultBlockOrder" : "2", 
      "blockId" : "2", 
      "data" : "1120", 
      "label" : "Baseline", 
      "quarter" : "", 
      "dataType" : { 
       "typeId" : "1" 
      }, 
      "tooltip" : { 
       "enable" : true, 
       "text" : "" 
      } 
     }, 
     { 
      "defaultBlockOrder" : "3", 
      "blockId" : "3", 
      "data" : "1200", 
      "label" : "Projected", 
      "quarter" : "", 
      "dataType" : { 
       "typeId" : "1" 
      }, 
      "tooltip" : { 
       "enable" : true, 
       "text" : "" 
      } 
     } 
    ] 
} 

mongodb로 끝낼 수 있습니까? 나는 3.4를 사용하고 집계를 사용하여 이것을 달성하려고 노력하고있다.

미리 감사드립니다.

+0

지금까지 해보신 것은 무엇입니까? –

답변

1

다음 쿼리는 작업을 수행합니다

db.merge.aggregate([ 
    // unwind twice 
    {$unwind: "$templateBlocks"}, 
    {$unwind: "$dataBlocks"}, 
    // get rid of documents where dataBlocks.blockId and 
    // templateBlocks.blockId are not equal 
    {$redact: {$cond: [{ 
         $eq: [ 
           "$dataBlocks.blockId", 
           "$templateBlocks.blockId" 
          ] 
         }, 
         "$$KEEP", 
         "$$PRUNE" 
        ] 
      } 
    }, 
    // merge dataBlocks and templateBlocks into a single document 
    {$project: { 
       bacId: 1, 
       cardId: 1, 
       defaultCardOrder: 1, 
       alias: 1, 
       label: 1, 
       for: 1, 
       cardTooltip: 1, 
       dataBlocks: { 
           defaultBlockOrder: "$dataBlocks.defaultBlockOrder", 
           blockId: "$dataBlocks.blockId", 
           data: "$dataBlocks.data", 
           label: "$templateBlocks.label", 
           quarter: "$templateBlocks.quarter", 
           data: "$templateBlocks.data", 
           dataType: "$templateBlocks.dataType", 
           tooltip: "$templateBlocks.tooltip" 
          } 
      } 
     }, 
     // group to put correspondent dataBlocks to an array 
     {$group: { 
       _id: { 
        _id: "$_id", 
        bacId: "$bacId", 
        cardId: "$cardId", 
        defaultCardOrder: "$defaultCardOrder", 
        alias: "$alias", 
        label: "$label", 
        for: "$for", 
        cardTooltip: "$cardTooltip" 
        }, 
       dataBlocks: {$push: "$dataBlocks" } 
      } 
    }, 
    // remove the unnecessary _id object 
    {$project: { 
       _id: "$_id._id", 
       bacId: "$_id.bacId", 
       cardId: "$_id.cardId", 
       defaultCardOrder: "$_id.defaultCardOrder", 
       alias: "$_id.alias", 
       label: "$_id.label", 
       for: "$_id.for", 
       cardTooltip: "$_id.cardTooltip", 
       dataBlocks: "$dataBlocks" 
      } 
    } 
]) 

두 번 성능은 쿼리로 데이터 세트의 크기 의존 계정으로 풀려 가지고는 중간 서류의 많은 양을 생산할 수 있습니다.

+0

감사합니다. 그것은 내 하루를 구했다. –

1

아래에서 3.6에서 시도해 볼 수 있습니다.

아래 쿼리는 dataBlocks 배열을 반복하고 데이터 블록 요소를 템플릿 블록 요소와 병합합니다. 템플릿 블록은 일치하는 블록 ID와 $arrayElemAt을 갖는 배열 인덱스를 찾아 발견 된 인덱스의 요소에 액세스하는 $indexofArray을 사용하여 조회됩니다. 3.4

db.collection_name.aggregate([{"$addFields":{ 
    "blocks":{ 
    "$map":{ 
     "input":"$dataBlocks", 
     "in":{ 
     "$mergeObjects":[ 
      "$$this", 
      {"$arrayElemAt":[ 
      "$templateBlocks", 
      {"$indexOfArray":["$templateBlocks","$$this.blockId"]} 
      ] 
      } 
     ] 
     } 
    } 
    } 
}}]) 

두 어레이에서 각각의 배열 요소를 병합 $arrayToObject, $objectToArray$concatArrays과의 조합으로 대체 $mergeObjects.

db.collection_name.aggregate([{"$addFields":{ 
    "blocks":{ 
    "$map":{ 
     "input":"$dataBlocks", 
     "in":{ 
     "$arrayToObject":{ 
      "$concatArrays":[ 
      {"$objectToArray":"$$this"}, 
      {"$objectToArray":{ 
       "$arrayElemAt":[ 
       "$templateBlocks", 
       {"$indexOfArray":["$templateBlocks","$$this.blockId"] 
       } 
       ] 
      }} 
      ] 
     } 
     } 
    } 
    } 
}}]) 

예외가있는 프로젝트를 마지막 단계로 사용하여 출력에서 ​​배열 필드를 제거 할 수 있습니다.

{"$project":{"templateBlocks":0,"dataBlocks":0}} 
관련 문제