简体   繁体   English

使用条件合并结果在 mongo 查询中

[英]Merge results in mongo query with conditions

Use case:用例:

I have n number of jobs, I want to merge the data for those jobs such that if value to corresponding subkey is passed in 1 case, it should mark it as passed.我有 n 个作业,我想合并这些作业的数据,这样如果在 1 种情况下传递了对应子键的值,它应该将其标记为已通过。

eg Job1 Detailed Object:例如 Job1 详细 Object:

{"Name" : [{"No." : "119","Time" : "t"}],
"Results":[{**"K1"** : {"Counters" : x, "TCR" : [{"Name" : "K11", "Result" : "PASSED"}, 
                                             {"Name" : "K12","Result" : **"FAILED"**},
                                             {"Name" : "K13","Result" : **"PASSED"**}]
                    },
            "K2" : {"Counters": y, "TCR" : [{"Name" : "K21","Result" : "PASSED"},              
                                            {"Name" : "K22","Result" : "PASSED"}]
                      
                    }
            
           ]
}

Job2 Detailed Object: Job2详细Object:

{"Name" : [{"No." : "120","Time" : "t1"}],
"Results":[{"**K1"** : {"Counters" : x, "TCR" : [{"Name" : "K11", "Result" : "PASSED"}, 
                                             {"Name" : "K12","Result" : **"PASSED"**},
                                             {"Name" : "K13","Result" : **"FAILED"**}]
                    },
            "K3" : {"Counters": y, "TCR" : [{"Name" : "K31","Result" : "PASSED"},              
                                            {"Name" : "K32","Result" : "PASSED"}]
                      
                    }
            
           ]
}

Expected Output预计 Output

{"Name" : [{"No." : "119-120","Time" : "lowest(t,t1)"}],
"Results":[{**"K1"** : {"Counters" : x, "TCR" : [{"Name" : "K11", "Result" : "PASSED"}, 
                                             {"Name" : "K12","Result" : **"PASSED"**},
                                             {"Name" : "K13","Result" : **"PASSED"**}]
                    },
            "K2" : {"Counters": y, "TCR" : [{"Name" : "K21","Result" : "PASSED"},              
                                            {"Name" : "K22","Result" : "PASSED"}]
                      
                    },
             "K3" : {"Counters": y, "TCR" : [{"Name" : "K31","Result" : "PASSED"},              
                                            {"Name" : "K32","Result" : "PASSED"}]
                      
                    }
            
           ]
}

Explanation:解释:

Key k1 is common in both dicts, so inside k1, we have key k12 and k13, which are passed in one but failed in other.密钥 k1 在两个 dicts 中都是通用的,因此在 k1 内部,我们有密钥 k12 和 k13,它们在一个中传递但在另一个中失败。 So, in expected output, I need key k1 with keys k12 and k13 having value as passed, as they are passed in one case.因此,在预期的 output 中,我需要键 k1 和键 k12 和 k13 具有传递的值,因为它们在一种情况下被传递。 Along with that, K2 and K3 will come as it is.与此同时,K2 和 K3 将按原样出现。

I reached till point where I aggregated same key data in one row, but how to proceed for further comparisons.我达到了将相同的关键数据汇总在一行中的位置,但是如何进行进一步的比较。

query using -查询使用 -

aggregate([{$match: {
  $or:[{"Name.No":"119"},{"Name.No":"120"}]
}}, {$project: {
  x:{$objectToArray:"$Results"}
}},{$unwind: "$x"},{$group: {_id: "$x.k", distinctVals: {$addToSet: "$x.v.TCR"}}}])

The name/result fields are:名称/结果字段是:
in an object that is在 object 中
in an array that is在一个数组中
embedded in an object that is嵌入在 object 中
embedded in another object that is嵌入在另一个 object 中
in an array that is在一个数组中
embedded in the document.嵌入文档中。

Thats a lot of layers to peel.那是很多层要剥。

So to get to the name/result pairs:所以要获得名称/结果对:

  • unwind array in the document展开文档中的数组
  • convert the embedded objects to arrays将嵌入对象转换为 arrays
  • unwind the converted arrays展开转换后的 arrays
  • reach into the last document and unwind the deep array进入最后一个文档并展开深度数组

Then to combine them然后将它们结合起来

  • group by the name part, push all the pass/fail results into an array按名称部分分组,将所有通过/失败结果推送到数组中
  • reduce over the constructed array to determine the overall pass/fail value减少构造的数组以确定整体通过/失败值
  • group by the key (K1, K2, etc) and push the name/result into an array按键(K1、K2 等)分组并将名称/结果推送到数组中
  • group by null (ie no group making a single document) push they keys into a results array按 null 分组(即没有制作单个文档的组)将它们的键推入结果数组
  • reconstruct the document structure重构文档结构

Through all of those steps, maintain the global fields like Name and Time.通过所有这些步骤,维护名称和时间等全局字段。

That might look like:这可能看起来像:

db.collection.aggregate([
  {$match: {"Name.No": {$in:["119","120"]}}},
  {$unwind: "$Results"},
  {$set: {
      Results: {$objectToArray: "$Results"}
  }},
  {$unwind: "$Results"},
  {$unwind: "$Results.v.TCR"},
  {$group: {
      _id: {
        resultKey: "$Results.k",
        TCRName: "$Results.v.TCR.Name"
      },
      Result: {$push: "$Results.v.TCR.Result"},
      Counters: {$first: "$Results.v.Counters"},
      No: {$addToSet: "$Name.No"},
      Time: { $min: "$Name.Time"}
  }},
  {$set: {
      No: {
        $reduce: {
          input: "$No",
          initialValue: [],
          in: {$setUnion: ["$$value","$$this"]}
        }
      },
      Result: {
        $cond: {
          if: {$in: ["PASSED","$Result"]},
          then: "PASSED",
          else: "FAILED"
        }
      }
  }},
  {
    $group: {
      _id: "$_id.resultKey",
      No: {$addToSet: "$No"},
      Time: {$min: "$Time"},
      Counters: {$first: "$Counters"},
      TCR: {
        $push: {
          $arrayToObject: [
            [
              {"k": "name","v": "$_id.TCRName"},
              {"k": "Result",v: "$Result"}
            ]
          ]
        },
        
      }
  }},
  {$set: {
      No: {
        $reduce: {
          input: "$No",
          initialValue: [],
          in: {$setUnion: ["$$value","$$this"]}
        }
      }
  }},
  {$group: {
      _id: null,
      No: {$push: "$No"},
      Time: {$min: "$Time"},
      Results: {
        $push: {"k": "$_id",
                "v": {
                      Counters: "$Counters",
                      TCR: "$TCR"
                     }
               }
      }
  }},
  {$project: {
      Name: {
        No: {
          $reduce: {
            input: "$No",
            initialValue: [],
            in: {$setUnion: ["$$value","$$this"]}
          }
        },
        Time: {$min: "$Time"}
      },
      Results: {$arrayToObject: "$Results"}
  }}
])

Playground操场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM