如何使用数据库命令重命名数组中的字段?

13 浏览
0 Comments

如何使用数据库命令重命名数组中的字段?

免责声明:尽管相似,但与MongoDB重命名数组中的数据库字段不同。我想要使用数据库命令而不是shell将字段的键从name更改为title。我发现在数组内部使用$rename是不可能的。因此,我转而使用$set$unset,创建了以下命令:

db.runCommand({
    update: 'apps',
    updates: [
        {
            q: {versions: {$elemMatch: {title: {$exists: false}}}},
            u: {
                $set: {'versions.$.title': '$name'}
            },
            multi: true
        },
        {
            q: {versions: {$elemMatch: {name: {$exists: true}}}},
            u: {
                $unset: {'versions.$.name': ''}
            },
            multi: true
        }
    ]
})

这部分代码基本能够实现我的要求,但它将所有的title/name都更改为字符串"$name",而不是字段name的值。

我还尝试了以下代码:

db.runCommand({
    update: 'apps',
    updates: [
        {
            q: {versions: {$elemMatch: {title: {$exists: false}}}},
            u: {
                $set: {
                    versions: {
                        $map: {
                            input: "versions",
                            as: 'each',
                            in: {
                                "title": "$$each.name"
                            }
                        }
                    }
                }
            },
            multi: true
        },
        {
            q: {versions: {$elemMatch: {name: {$exists: true}}}},
            u: {
                $unset: {'versions.$.name': ''}
            },
            multi: true
        }
    ]
})

但是这只会导致错误[在'versions.$map'中以'$map'为前缀的字段'$'是无效的存储。]。我该如何在数组内部重命名字段?

以下是我apps集合的精简版本供参考。我只想将名为name的键更改为title

[{
  identifier: "x",
  versions: [
    {
      name: "test_name"
      version: "x.x.x"
    },
    {
      name: "test_name"
      version: "x.x.x"
    },
  ]
},
{
  identifier: "y",
  versions: [
    {
      name: "test_name2"
      version: "x.x.x"
    },
    {
      name: "test_name2"
      version: "x.x.x"
    },
  ]
}, ... ]

0
0 Comments

如何使用数据库命令重命名数组中的字段?

问题的原因:错误消息提示无效的字段名称,无法存储带有$前缀的字段。

解决方法:

1. 更新聚合管道中的数组字段时,将u对象放在数组括号中。

2. 在$map中同时放入要重命名的字段title和version。

3. 不需要使用$unset,因为$map将使用新字段替换旧数据。

以下是使用数据库命令更新数组字段的示例代码:

db.runCommand({
    update: 'apps',
    updates: [
        {
            q: { "versions.name": { $exists: true } },
            u: [{
                $set: {
                    versions: {
                        $map: {
                            input: "$versions",
                            in: {
                                "title": "$$this.name",
                                "version": "$$this.version"
                            }
                        }
                    }
                }
            }],
            multi: true
        }
    ]
})

另一种更动态的方法是使用$mergeObjects和$unset来更新数组字段,代码如下:

db.runCommand({
    update: 'apps',
    updates: [
        {
            q: { "versions.name": { $exists: true } },
            u: [
              {
                $set: {
                    versions: {
                        $map: {
                            input: "$versions",
                            in: {
                                $mergeObjects: [
                                    "$$this",
                                    { "title": "$$this.name" }
                                ]
                            }
                        }
                    }
                }
              },
              { $unset: "versions.name" }
            ],
            multi: true
        }
    ]
})

如果没有$map,是否有其他方法遍历数组?

在Azure CosmosDB for MongoDB(3.6版本)中,不支持$map。也无法使用聚合管道进行更新。

0