はじめに
MongoDB Shellで複数のDBに対し、一気に更新することは出来ないかなーって考えたのでその際の備忘録です。
一つのDBに対する更新はともかく、それを複数のDBに展開しようとすると手作業だとかなり面倒ですしね。
構造が同じDBが複数存在している時にしか使えないので、他の人にとって役立つか?というと微妙ですが…
実際の処理
さて、早速ですが本題のスクリプトになります。
const dbNames = db.getMongo().getDBNames();
dbNames.forEach((dbName) => {
const currentDB = db.getSiblingDB(dbName);
// 以下、各DBで実行したい処理を行う
currentDB.any_collection.updateMany({}, { $set: { test: true } });
currentDB.any_collection.createIndex({ key: 1 }, { name: 'INDEX_TEST' });
// ここまで
});
db.getMongo()
でMongoDBのインスタンスを取得し、getDBNames()
でDB名を配列で取得します。
あとは取得したDB名をループし、db.getSiblingDB(dbName)
で対象DBのオブジェクトを取得して各クエリを実行していきます。
こう見ると単純ではありますが、通常ではまず使わないようなメソッドを使うので普通にMongoDBを使っているだけだと知ることは恐らくほぼ無いです。
通常のアプリでDB跨ぐような処理ってまずやらないし…
全部のDBだけじゃなくて一部特定のDBだけでいいなら、上記のdbNames
に固定で配列を記述するなど応用すれば使える機会はもっと増えそうです。
getDBNames()
はDBに接続しているユーザーが権限を持っているDB名を返します。
つまり、ユーザーによってはadmin
やconfig
などのDB名も取得され、処理の対象となってしまいます。
DB権限を制限しているユーザーで接続する、if文で対象のDBを判定するなど対策の上使用してください。
余談:試したこと
本題は終わっていますが、上記に辿り着くまでの経緯も備忘録として記載しておきます。
まずDB名を取得する方法ですが、単にリストが見えればいいのであればshow dbs
というコマンドもあります。
> show dbs
< admin 40.00 KiB
config 96.00 KiB
local 72.00 KiB
sandbox 72.00 KiB
ただこれは変数で受け取れないので、後続の処理に使うことはできません。あくまで見るだけですね。
また、DBの切り替えならuse DB名
というコマンドもあります。
普通にMongoDB ShellでDBの切り替えを行うならこのコマンドですね。
> use sandbox
< switched to db sandbox
最初はdb.getSiblingDB(dbName)
の代わりにこれを使おうとしていましたが、後続のクエリが実行されないのでこれも今回は使えませんでした。
普通の切り替えならuseでよいので、用途によってちゃんと使い分けていきたいですね。