在 MongoDB 聚合期间,我需要更新嵌套字段的值,但该字段的名称是另一个字段的值。示例文档:
{
"prop": {
"nestedField": "oldValue" // Property to be updated
},
"keyPath": "prop.nestedField", // Path to the target field using dot notation
"val": "newValue" // New value to set to target field
}
因此聚合后它应该变成:
{
"prop": {
"nestedField": "newValue" // Value has been updated
},
...
}
保证该路径存在于文档中。
我尝试使用$arrayToObject
,但对于嵌套的键路径,它将值解释为文字,并创建具有键路径的精确值(如"prop.nestedField"
)而不是嵌套对象的字段。
当然,这可以在聚合之后完成,但接下来的阶段需要使用更新的数据,所以我有兴趣在聚合内部执行此操作。
这个问题困扰了好几天,非常希望得到一些帮助
编辑:想出了一种复杂的方法来实现超过 1 层的嵌套。这个想法是类似的:构造一个更新对象并将
$mergeObject
。$$ROOT
可以使用 动态构造更新对象$reduce
。Mongo Playground 中的完整代码
高度嵌套的文档和使用动态值作为字段名称被视为反模式,应避免使用。如果可能,请考虑重构您的架构。
但是对于您当前的情况,如果中的值
keyPath
仅嵌套了 1 层,则仍然可以通过使用动态构造更新对象$arrayToObject
并将$mergeObjects
其合并到$$ROOT
对象来实现管理。$split
分解$keyPath
为包含外层字段名称prop
和内层字段名称的数组nestedField
$arrayToObject
两次构造更新对象,借助$first
和$last
来访问外层和内层字段名称。更新对象应如下所示:$mergeObjects
合并更新对象到$$ROOT
$replaceWith
保存更新$unset
辅助字段tokens
蒙戈游乐场
注意:如果您的
keyPath
嵌套不止一次,则此解决方案不太可能扩展以构造动态级别的更新对象,因此无法应用。即使可以这样做,也会引入大量代码异味并使查询无法维护。再次,建议尽可能重构架构。