1

我对 MongoDB 很陌生,我需要对我的集合进行一些复杂的更新操作。

我有这样的收藏:

[
  {
    "Id": 1,
    "extension": [
      {
        "keyName": "Name",
        "value": "Bob"
      },
      {
        "keyAge": "Age",
        "value": 20
      }
    ]
  },
  {
    "Id": 2,
    "extension": [
      {
        "keyName": "Name",
        "value": "Sam"
      },
      {
        "key": "Name",
        "value": "Sam"
      }
    ]
  },
  {
    "Id": 3,
    "extension": [
      {
        "keyName": "Age",
        "value": 25
      },
      {
        "key": "Age",
        "value": 25
      }
    ]
  },
  {
    "Id": 4
  }
]

我想更新extension所有文档数组中的任何项目

以便在找到具有key属性的项目时,将其重命名keyAge

这是预期的结果:

[
  {
    "Id": 1,
    "extension": [
      {
        "keyName": "Name",
        "value": "Bob"
      },
      {
        "keyAge": "Age",
        "value": 20
      }
    ]
  },
  {
    "Id": 2,
    "extension": [
      {
        "keyName": "Name",
        "value": "Sam"
      },
      {
        "keyAge": "Name",
        "value": "Sam"
      }
    ]
  },
  {
    "Id": 3,
    "extension": [
      {
        "keyName": "Age",
        "value": 25
      },
      {
        "keyAge": "Age",
        "value": 25
      }
    ]
  },
  {
    "Id": 4
  }
]

我尝试以$rename与此问题类似的方式使用: MongoDB rename database field within array but I get the same error$rename source may not be dynamic array

我认为这个解决方案也可能适用于我,我尝试使用它,但它并没有更新我的任何东西,所以我想我无法理解如何将这个答案应用于我...... https://stackoverflow.com/a/49193743 /215553

谢谢您的帮助!

4

2 回答 2

1

我尝试以$rename与此问题类似的方式使用:MongoDB rename database field within array but I get the same error$rename source may not be dynamic array

$rename中有一条注释:

$rename如果这些字段在数组元素中,则不起作用。

您可以尝试从 MongoDB 4.2 开始使用聚合管道进行更新,

  • 检查条件 idkey字段是否存在
  • $mapextension迭代数组的循环
  • $mapextension以键值格式迭代从对象转换为数组的数组循环
  • $cond检查条件如果kkey则返回keyAge否则返回当前
  • $arrayToObject返回将上面映射的键值数组返回转换为对象原始格式
db.collection.update(
  { "extension.key": { $exists: true } },
  [{
    $set: {
      extension: {
        $map: {
          input: "$extension",
          in: {
            $arrayToObject: {
              $map: {
                input: { $objectToArray: "$$this" },
                in: {
                  k: {
                    $cond: [
                      { $eq: ["$$this.k", "key"] }, // check "key" field name
                      "keyAge", // update new name "keyAge"
                      "$$this.k"
                    ]
                  },
                  v: "$$this.v"
                }
              }
            }
          }
        }
      }
    }
  }],
  { multi: true }
)

操场

于 2021-04-28T14:26:04.647 回答
0

这适用于您的情况。虽然可能不是最易读的。

import json

data = json.loads(strdata)
for entry in data:
    if 'extension' in entry:
        for x in entry['extension']:
            for k, v in x.items():
                if k == 'key':
                    x['keyAge'] = x.pop(k)
于 2021-04-28T14:28:31.703 回答