1

私は、このフォーマットでデータを取得している集約の結果が1つある状況があります。異なる配列の2つの一致するオブジェクトを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」Sに基づいて、その「データブロック」と「templateBlocks」この場合には、ここで、行ごとに2つのオブジェクトの配列を比較したいと私は次の形式で結果を取得したいです。

{ 
    "_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配列を反復し、データブロック要素をテンプレートブロック要素とマージします。テンプレートブロックは、$indexofArrayを使用して検索され、一致するブロックIDおよび$arrayElemAtを持つ配列インデックスが検索されたインデックスの要素にアクセスします。 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}} 
関連する問題