基于键合并两个数组并使用 mongo 聚合添加新字段

Merge two arrays based on a key and add new filed using mongo aggregation

我需要编写一个聚合来使用条件将一个数组字段合并到另一个数组字段中。

示例: 原文档:

[{
        "key": 1,
        "risks": [{
                "_id": "1234-risk1",
                "name": "risk1"
            }, {
                "_id": "9999-risk2",
                "name": "risk2"
            }
        ],
        "controls": [{
                "identifier": "P8.1.3",
                "links": [{
                        "entity": {
                            "valueKey": "1234-risk1"
                        }
                    }, {
                        "entity": {
                            "valueKey": "456"
                        }
                    }
                ]
            }, {
                "identifier": "X8.1.3",
                "links": [{
                        "entity": {
                            "valueKey": "1234-risk1"
                        }
                    }, {
                        "entity": {
                            "valueKey": "456"
                        }
                    }
                ]
            }, 
            {
                "identifier": "Y8.1.3",
                "links": [{
                        "entity": {
                            "valueKey": "9999-risk2"
                        }
                    }, {
                        "entity": {
                            "valueKey": "456"
                        }
                    }
                ]
            },
            {
                "identifier": "A1.2.9",
                "links": [{
                        "entity": {
                            "valueKey": "456"
                        }
                    }
                ]
            }
        ]
    }
]

字段risks.id(例如:1234-risk1 和9999-risk2)在控件数组字段中有相关控件。 还有一些控件不匹配任何 risk.id 匹配项。

我需要创建一个新的字段 riskControls 来 club risk + 其相应的控制(如果有的话),然后控制没有风险。

预计:

[{
        "key": 1,
        "riskControls": [{
                "_id": "1234-risk1",
                "name": "risk1",
                "controls": [{
                        "identifier": "P8.1.3",
                        "links": [{
                                "entity": {
                                    "valueKey": "1234-risk1"
                                }
                            }, {
                                "entity": {
                                    "valueKey": "456"
                                }
                            }
                        ]
                    }, {
                        "identifier": "X8.1.3",
                        "links": [{
                                "entity": {
                                    "valueKey": "1234-risk1"
                                }
                            }, {
                                "entity": {
                                    "valueKey": "456"
                                }
                            }
                        ]
                    }
                ]
            }, {
                "_id": "9999-risk2",
                "name": "risk2",
                "controls": [{
                        "identifier": "Y8.1.3",
                        "links": [{
                                "entity": {
                                    "valueKey": "9999-risk2"
                                }
                            }, {
                                "entity": {
                                    "valueKey": "456"
                                }
                            }
                        ]
                    }
                ]
            }, {
                //no risk details
                "controls": [{
                        "identifier": "A1.2.9",
                        "links": [{
                                "entity": {
                                    "valueKey": "456"
                                }
                            }
                        ]
                    }
                ]
            }
        ]
    }
]

https://mongoplayground.net/p/MbRciOaKMHO

查询

  • 找到控件 ID(值键)
  • 找到 rnc-id(没有控制 id 的风险)
  • 找到 cnr-id (>>)
  • 用它来制作 3 个数组
    • rnc = 无法控制的风险
    • cnr = 没有风险的控件
    • rc = 可控的风险
  • 连接所有 3
  • 取消所有临时字段和风险控制

*查询很大,但是一个风险可能没有控制,一个控制可能没有风险,所以它就像 3 个风险与控制的匹配

PlayMongo

aggregate(
[{"$set": 
    {"controls-ids": 
      {"$reduce": 
        {"input": "$controls.links.entity.valueKey",
          "initialValue": [],
          "in": {"$concatArrays": ["$$value", "$$this"]}}}}},
  {"$set": 
    {"rnc-ids": {"$setDifference": ["$risks._id", "$controls-ids"]},
      "cnr-ids": {"$setDifference": ["$controls-ids", "$risks._id"]}}},
  {"$unset": ["controls-ids"]},
  {"$set": 
    {"cnr": 
      {"$map": 
        {"input": 
          {"$filter": 
            {"input": "$controls",
              "cond": 
              {"$eq": 
                [{"$setDifference": 
                    ["$$this.links.entity.valueKey", "$cnr-ids"]},
                  []]}}},
          "in": {"controls": "$$c"},
          "as": "c"}},
      "rnc": 
      {"$map": 
        {"input": 
          {"$filter": 
            {"input": "$risks", "cond": {"$in": ["$$this._id", "$rnc-ids"]}}},
          "in": {"$mergeObjects": ["$$r", {"controls": []}]},
          "as": "r"}},
      "rc": 
      {"$map": 
        {"input": 
          {"$filter": 
            {"input": "$risks",
              "cond": {"$not": [{"$in": ["$$this._id", "$rnc-ids"]}]}}},
          "in": 
          {"$mergeObjects": 
            ["$$r",
              {"controls": 
                {"$filter": 
                  {"input": "$controls",
                    "cond": {"$in": ["$$r._id", "$$c.links.entity.valueKey"]},
                    "as": "c"}}}]},
          "as": "r"}}}},
  {"$set": {"riskControls": {"$concatArrays": ["$rc", "$rnc", "$cnr"]}}},
  {"$unset": 
    ["controls-ids", "rnc-ids", "cnr-ids", "cnr", "rnc", "rc", "risks",
      "controls"]}])