You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB动态键路径匹配查询与批量更新问题

问题描述

现有MongoDB文档结构如下:

{
    "_id": "1234",
    "Nodes": {
        "-14": {
            "_t": "DL",
            "Key": "-14",
            "Edges": [
                {
                    "TargetNode": "-5"
                }
            ],
            "Title": "Lookup",
            "Text": "Data Lookup",
            "ConnectionString": "Server=LOCALSERVER;Database=DataCache;User=sa;Password=1234;",
            "TableName": "Customers",
            "FieldMaps": [
                {
                    "ID": 2,
                    "Column": "Name"
                },
                {
                    "ID": 1,
                    "Column": "Number"
                }
            ]
        }
    }
}

需要执行updateMany操作,将所有文档中Nodes下任意动态负数值键对应的ConnectionString里的Server=LOCALSERVER替换为Server=NEWSERVER。但当前查询环节遇到问题:Nodes下的节点ID(如-14)是随文档变化的动态值,使用固定键名的查询只能匹配特定文档,而MongoDB不支持直接在键名中使用正则匹配。

尝试过的无效查询:

db.getCollection('workflows').find({"Nodes.{$regex: '-\\d{1,}'}.ConnectionString": {$regex: /^Server=LOCALSERVER/}})
解决方案

1. 查询匹配文档

利用$expr结合$objectToArray将Nodes对象转换为键值对数组,再通过$anyElementTrue检查是否存在符合条件的节点:

db.getCollection('workflows').find({
  $expr: {
    $anyElementTrue: {
      $map: {
        input: { $objectToArray: "$Nodes" },
        as: "node",
        in: {
          $and: [
            // 匹配键为负数值格式(可选,若只需要负数值键的节点)
            { $regexMatch: { input: "$$node.k", regex: /^-\d+$/ } },
            // 匹配ConnectionString包含目标值
            { $regexMatch: { input: "$$node.v.ConnectionString", regex: /^Server=LOCALSERVER/ } }
          ]
        }
      }
    }
  }
})

如果不需要限制节点键为负数值格式,可去掉$and中的第一个条件。

2. 执行批量更新

使用聚合管道模式的updateMany,通过$objectToArray、$map和$arrayToObject动态遍历并修改所有符合条件的节点:

db.getCollection('workflows').updateMany(
  // 查询条件同上述查询语句
  {
    $expr: {
      $anyElementTrue: {
        $map: {
          input: { $objectToArray: "$Nodes" },
          as: "node",
          in: {
            $and: [
              { $regexMatch: { input: "$$node.k", regex: /^-\d+$/ } },
              { $regexMatch: { input: "$$node.v.ConnectionString", regex: /^Server=LOCALSERVER/ } }
            ]
          }
        }
      }
    }
  },
  [
    {
      $set: {
        Nodes: {
          $arrayToObject: {
            $map: {
              input: { $objectToArray: "$Nodes" },
              as: "node",
              in: {
                k: "$$node.k",
                v: {
                  $mergeObjects: [
                    "$$node.v",
                    {
                      ConnectionString: {
                        $cond: [
                          {
                            $and: [
                              { $regexMatch: { input: "$$node.k", regex: /^-\d+$/ } },
                              { $regexMatch: { input: "$$node.v.ConnectionString", regex: /^Server=LOCALSERVER/ } }
                            ]
                          },
                          // 替换目标字符串
                          { $replaceOne: { input: "$$node.v.ConnectionString", find: "Server=LOCALSERVER", replacement: "Server=NEWSERVER" } },
                          // 不符合条件的保持原字符串
                          "$$node.v.ConnectionString"
                        ]
                      }
                    }
                  ]
                }
              }
            }
          }
        }
      }
    }
  ]
)

关键逻辑说明

  • $objectToArray: 将Nodes对象转换为[{k: "键名", v: "值对象"}]格式的数组,方便遍历处理动态键。
  • $map: 遍历数组中的每个节点,对符合条件的节点执行字符串替换。
  • $arrayToObject: 将处理后的数组转换回对象格式,更新原Nodes字段。
  • $mergeObjects: 保留节点原有其他字段,只修改ConnectionString。

内容的提问来源于stack exchange,提问作者Mate19

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 19:05:56