基于键合并两个数组并使用 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"
}
}
]
}
]
}
]
}
]
查询
- 找到控件 ID(值键)
- 找到 rnc-id(没有控制 id 的风险)
- 找到 cnr-id (>>)
- 用它来制作 3 个数组
- rnc = 无法控制的风险
- cnr = 没有风险的控件
- rc = 可控的风险
- 连接所有 3
- 取消所有临时字段和风险控制
*查询很大,但是一个风险可能没有控制,一个控制可能没有风险,所以它就像 3 个风险与控制的匹配
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"]}])
我需要编写一个聚合来使用条件将一个数组字段合并到另一个数组字段中。
示例: 原文档:
[{
"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"
}
}
]
}
]
}
]
}
]
查询
- 找到控件 ID(值键)
- 找到 rnc-id(没有控制 id 的风险)
- 找到 cnr-id (>>)
- 用它来制作 3 个数组
- rnc = 无法控制的风险
- cnr = 没有风险的控件
- rc = 可控的风险
- 连接所有 3
- 取消所有临时字段和风险控制
*查询很大,但是一个风险可能没有控制,一个控制可能没有风险,所以它就像 3 个风险与控制的匹配
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"]}])