【问题标题】:How to rename keys of items in an array如何重命名数组中项目的键
【发布时间】:2021-07-21 21:50:05
【问题描述】:

我对 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
  }
]

我尝试以与此问题类似的方式使用$renameMongoDB rename database field within array 但我得到同样的错误$rename source may not be dynamic array

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

感谢您的帮助!

【问题讨论】:

    标签: node.js mongodb mongodb-query aggregation-framework


    【解决方案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 开始尝试update with aggregation pipeline

    • 检查条件 id key 字段是否存在
    • $map 迭代 extension 数组的循环
    • $map 迭代从 extension 对象转换为键值格式数组的数组循环
    • $cond 检查条件如果kkey 然后返回keyAge 否则返回当前
    • $arrayToObject 将上面map返回的key-value数组转换为object原始格式
    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 }
    )
    

    Playground

    【讨论】:

    • 这很奇怪,它在操场上工作,但当我在 MongoDBCompass 中对我的数据执行查询时却不行...{ acknowledged: true, insertedId: null, matchedCount: 0, modifiedCount: 0, upsertedCount: 0 }
    • 你能展示一下你是如何在 monbodb compass 中执行这个查询的吗?我建议在 mongo shell 中进行这种操作,因为 mongodb compass 仍处于 beta 版本。
    • 像这样:i.imgur.com/C8OmiYn.png 我会尽力理解...我认为你的答案是正确的 :) 谢谢!
    • 啊第一个命令use <your database name> 第二个使用你的集合名称db.<your collection name>.update(..
    【解决方案2】:

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

    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)
    

    【讨论】:

    • 感谢您的回答!这可以从 MongoDB Compass 运行吗?我习惯做 db.collection.updateMany...等。
    • 另外,我认为我需要使用 Mongo 聚合管道来提高性能...我有成千上万的文档要以这种方式更新
    猜你喜欢
    • 2022-08-19
    • 2020-11-26
    • 2018-05-17
    • 1970-01-01
    • 2012-03-25
    • 1970-01-01
    • 2020-05-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多