やりたいこと
MongoDBを使った開発を行ってきたが現物とドキュメントとの乖離が出てきたり、他人が設計したものの面倒を見ることになってしまうことが出てきた。なので現物からデータベース/コレクション/インデックスを抜き出し視覚化して概要を把握したい・ドキュメント化したい。
RDBMSでER図を作成するSchemaSpyみたいなことをしたい感じ。
結果としての出力は
- テキストでツリー形式
- CSV形式(Excelで読んだり…)
- PlantUML
が選べる様にしたい。
方法
MongoDBは内部でJavaScriptを実行できるので、これでデータベース一覧→コレクション一覧→インデックスの順で順次取得するスクリプトを書いた。
MongoDBでJavaScriptはこんな感じで実行できる。
$ mongosh mongodb://server:port -f script.js
できたもの
コメント入れて100行以下なので貼っておく。
getMongoCollections.js
// 出力フォーマットを得る
const format = process.env.FORMAT || 'text';
// ヘッダー出力
if (format === 'csv') {
print('Database,Collection,Index');
} else if (format === 'plantuml') {
print('@startuml');
print('left to right direction');
print('scale 300 width');
}
// データベース一覧を取得
const databases = db.adminCommand('listDatabases').databases;
// データベースをそれぞれ調べる
databases.forEach(database => {
const dbName = database.name;
// システムデータベースは無視する
if (dbName === 'admin' || dbName === 'config' || dbName === 'local') {
return;
}
// データベース名を表示
if (format === 'csv') {
print(`${dbName},,`);
} else if (format === 'plantuml') {
print(`database ${dbName} {`);
} else {
print(`Database: ${dbName}`);
}
// データベースを切り替え
const currentDb = db.getSiblingDB(dbName);
// コレクション一覧を取得
const collections = currentDb.getCollectionNames();
// コレクションを調べる
collections.forEach(collection => {
// コレクション名を表示
if (format === 'csv') {
print(`,${collection},`);
} else if (format === 'plantuml') {
print(` folder ${collection} {`);
} else {
print(` Collection: ${collection}`);
}
// インデックス一覧を取得
const indexList = currentDb.getCollection(collection).getIndexKeys();
// インデックスのヘッダーを表示(PlantUML)
if (format === 'plantuml') {
print(` card ${collection.replaceAll("-", "_")}_index [`); // PlantUML対策
print(` Index`);
}
// 各インデックスに対して処理を行う
indexList.forEach(index => {
// インデックスを表示
if (format === 'csv') {
print(`,,"${JSON.stringify(index).replaceAll('"', '""')}"`);
} else if (format === 'plantuml') {
print(` ....`)
print(` ${JSON.stringify(index)}`);
} else {
print(` Index: ${JSON.stringify(index)}`);
}
});
// コレクション終了(PlantUML)
if (format === 'plantuml') {
print(` ]`);
print(` }`);
}
});
// データベース終了(PlantUML)
if (format === 'plantuml') {
print('}');
}
});
// フッター出力
if (format === 'plantuml') {
print('@enduml');
}
こちらにも置いておいた。
使用方法
FORMAT
環境変数にcsv
orplantuml
を入れるとそのフォーマットで表示される。そうでない場合テキストで。
# テキスト
$ mongosh mongodb://localhost:27017 -f getMongoCollections.js
# CSV
$ FORMAT=csv mongosh mongodb://localhost:27017 -f getMongoCollections.js > output.csv
# PlantUML
$ FORMAT=plantuml mongosh mongodb://localhost:27017 -f getMongoCollections.js > output.puml
サンプル出力結果
オープンソースのかんばんツールWekanはMongoDBを使っているので、それをDocker Composeで起動させその時のMongoDBのコレクション等をサンプルとして見てみる。
Compose.yaml
services:
wekan:
image: wekanteam/wekan
ports:
- "8080:8080"
depends_on:
- mongo
environment:
- ROOT_URL=http://localhost:8080
- MONGO_URL=mongodb://mongo:27017/wekan
mongo:
image: mongo:latest
volumes:
- wekan-data:/data/db
ports:
- "27017:27017"
volumes:
wekan-data:
テキスト
Database: wekan
Collection: accountSettings
Index: {"_id":1}
Index: {"modifiedAt":-1}
Collection: settings
Index: {"_id":1}
Index: {"modifiedAt":-1}
Collection: invitation_codes
Index: {"_id":1}
Index: {"email":1}
Index: {"modifiedAt":-1}
.
.
.
CSV
Markdownで例示するが、Execl等でも表にするとこんな感じ
Database | Collection | Index |
---|---|---|
wekan | ||
accountSettings | ||
{"_id":1} | ||
{"modifiedAt":-1} | ||
settings | ||
{"_id":1} | ||
{"modifiedAt":-1} | ||
invitation_codes | ||
{"_id":1} | ||
{"email":1} | ||
{"modifiedAt":-1} |
生のCSVだと
Database,Collection,Index
wekan,,
,accountSettings,
,,"{""_id"":1}"
,,"{""modifiedAt"":-1}"
,settings,
,,"{""_id"":1}"
,,"{""modifiedAt"":-1}"
,invitation_codes,
,,"{""_id"":1}"
,,"{""email"":1}"
,,"{""modifiedAt"":-1}"
.
.
.