データベース名を変更する
MongoDB にはデータベース名を直接変更するコマンドは存在しない。
そのため、通常はデータベースをコピーしてコピー元を削除する。
最新のバージョンでなければ、以下の方法でデータベースをコピーできる可能性がある。
> db.copyDatabase('old_dabatabase', 'new_database')
この方法は MongoDB 4.0 までは使えたが 4.2 以降では使えなくなっている。
4.2 以降ではコピー元を mongodump
して mongorestore
でデータベース名を変えてリストアする必要がある。
( copyDatabase
が提供される前はこの手法が使われていたので、古いやり方に戻ったとも言える)
コレクション名を変更する
以下のコマンドで user
から users
に変更できる。
> db.user.renameCollection("users")
{ "ok" : 1 }
コレクション名の変更にはドキュメントの件数は関係なく通常、一瞬で終わる。
フィールド名を変更する
フィールド名は $rename
を使えば変更できる。
(データベースの特性上、自然なことだが) こちらは1件ずつ更新が走るためそれなりに時間がかかる。
> db.users.find().count()
10000000
> db.users.update({}, { $rename: { 'nickname': 'alias' } }, false, true)
WriteResult({ "nMatched" : 10000000, "nUpserted" : 0, "nModified" : 10000000 })
1000万件のドキュメントに対してフィールド名を変更して、手元の環境では2分弱かかった。
(このあたりの時間は実行環境によって差が大きいと思うし、ローカルでの時間はあまり参考にはならないかもしれない)
ちなみに、コレクションの全件に対してフィールド名の変更を行っている途中に対象のフィールド名を用いた update を行うことで簡単に意図とは異なる処理が実現できる。
たとえば、上記の update コマンドを走らせてからすぐに別のコンソールで update を走らせると以下のようになる。
> db.users.update({nickname: {$exists: true}}, {$set: {has_nickname: true}}, false, true)
WriteResult({ "nMatched" : 9838702, "nUpserted" : 0, "nModified" : 9838702 })
変更されたのは約984万件。つまり16万件程度が更新されていないことになる。
インデックスを貼ったフィールドの名前を変更する
変更対象のフィールドにインデックスが貼ってあっても、特に問題はない。
(し、速くもならない)
また、 $rename
によってインデックスの情報は更新されない。
つまり、以下のケースでは update 後、どのドキュメントにも存在しないフィールド alias
にインデックスが貼られている状態になる。
> db.users.createIndex({alias: 1})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
> db.users.update({}, { $rename: { 'alias': 'nickname' } }, false, true)
WriteResult({ "nMatched" : 10000000, "nUpserted" : 0, "nModified" : 10000000 })
> db.users.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "sandbox.users"
},
{
"v" : 2,
"key" : {
"alias" : 1
},
"name" : "alias_1",
"ns" : "sandbox.users"
}
]
ちなみに unique index を貼っておくとエラーになる。
> db.users.createIndex({alias: 1}, {unique: true})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
> db.users.update({}, { $rename: { 'alias': 'nickname' } }, false, true)
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: sandbox.users index: alias_1 dup key: { alias: null }"
}
})