如何在 MongoDB 聚合管道中更新具有动态名称的嵌套字段的值?

问题描述 投票:0回答:1

在 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"
)而不是嵌套对象的字段。

当然,这可以在聚合后完成,但以下阶段需要使用更新的数据,所以我有兴趣在聚合内进行。

这几天一直在努力解决这个问题,非常感谢一些帮助

mongodb aggregation-framework
1个回答
0
投票

高度嵌套的文档和使用动态值作为字段名称被视为反模式,应避免。如果可能的话,请考虑重构您的架构。

但是对于您当前的场景,如果

keyPath
中的值仅嵌套 1 层,仍然可以通过使用
$arrayToObject
动态构造更新对象并使用
$mergeObjects
将其合并到
$$ROOT
对象来管理。

  1. $split
    $keyPath
    分解为包含外层字段名称
    prop
    和内层字段名称
    nestedField
  2. 的数组
  3. 使用
    $arrayToObject
    两次,借助
    $first
    $last
    构造更新对象,以访问外层和内层字段名称。更新对象应该如下所示:
{
    "prop": {
      "nestedField": "$val"
    } 
}
  1. 使用
    $mergeObjects
    将更新对象合并到
    $$ROOT
  2. 使用
    $replaceWith
    保存更新
  3. (可选)
    $unset
    辅助字段
    tokens
db.collection.update({},
[
  {
    "$set": {
      "tokens": {
        "$split": [
          "$keyPath",
          "."
        ]
      }
    }
  },
  {
    "$replaceWith": {
      "$mergeObjects": [
        "$$ROOT",
        {
          "$arrayToObject": [
            [
              {
                k: {
                  "$first": "$tokens"
                },
                v: {
                  "$arrayToObject": [
                    [
                      {
                        k: {
                          "$last": "$tokens"
                        },
                        v: "$val"
                      }
                    ]
                  ]
                }
              }
            ]
          ]
        }
      ]
    }
  },
  {
    "$unset": "tokens"
  }
])

蒙戈游乐场


注意:如果您的

keyPath
嵌套多次,则此解决方案不太可能扩展以构造动态级别的更新对象,因此无法应用。即使可以这样做,也会引入很多代码味道并使查询难以维护。再次强调,如果可能的话,建议重构架构。

© www.soinside.com 2019 - 2024. All rights reserved.