【问题标题】:Merge two arrays based on a key and add new filed using mongo aggregation基于键合并两个数组并使用 mongodb 聚合添加新字段
【发布时间】:2021-12-12 14:26:51
【问题描述】:

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

示例: 原始文档:

[{
        "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"
                        }
                    }
                ]
            }
        ]
    }
]

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

我需要创建一个新的字段 riskControls 到俱乐部风险 + 其相应的控制(如果有),然后控制没有风险。

预期:

[{
        "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

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework aggregation


    【解决方案1】:

    查询

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

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

    Test code here

    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"]}])
    

    【讨论】:

    • 感谢@Takis 的帮助。它适用于大多数场景,除了一种。它不起作用的情况是 - 当我有没有任何控制的风险时,“riskControls”字段会填充该风险对象两次。示例 - mongoplayground.net/p/zG1EfSc2Spy 在此示例中,“7777-risk2”在 riskControls 中出现了两次
    • 我更新了答案并且我认为现在可以工作,因为查询有点复杂和嵌套数组等,如果可以,请在使用前对其进行测试。
    • 谢谢,成功了。
    猜你喜欢
    • 2021-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-29
    • 2021-01-04
    • 2022-12-18
    • 1970-01-01
    • 2018-04-01
    相关资源
    最近更新 更多