表題のことをするためのライブラリ「Momy」をアップデートしたので、忘れないうちに記事にしておこうと思います。(アップデートの内容は、テスト追加が主です)
MongoDBはNoSQLなドキュメントデータベースなので、基本スキーマを持ちません。ただ、CouchDBなどとは異なり「コレクション」の概念があります。なので、若干強引ですが、コレクションをSQLのテーブルにマッピングすれば、MongoDBからMySQLへの一方向リプリケーションは比較的簡単に実現できます。
MongoDBはそのままだと、Microsoft Accessほかのオフィス系のツールから繋ぎにくいですが、MySQLに移してしまえば、各種ツール、ドライバがあります。MongoDBからRDBにリプリケーションするツールとしては、現在2つのツールがあります。(他にもあるかも)
| ライブラリ | レプリケーション | 実装 | 説明 |
|---|---|---|---|
| MoSQL | MongoDB → PostgreSQL | Ruby | Stripeが開発。残念ながら2年間メンテナンス停止状態。 |
| Momy | MongoDB → MySQL | Node | 去年、私がカッとなって作りました。 |
PostgreSQLを使う場合はMoSQLをどうぞ。あと、Apache Drillなども用途によっては選択肢に上がるかもしれません。
Momyのインストール
npmから入手できます。
$ npm install -g momy
スキーマ設定
スキーマレスとはいえ、実際にはアプリケーションが構造をある程度規定しているはずです。その「スキーマ」をmomyfile.jsonに設定します。基本的には、MongoDB(同期元)とMySQL(同期先)のデータベースを指定し、コレクションごとにフィールド名とその型を書いていけばOKです。
{
"src": "mongodb://localhost:27017/myapp",
"dist": "mysql://root@localhost:3306/myapp",
"collections": {
"contacts": {
"_id": "string",
"createdAt": "DATETIME",
"lastName": "string",
"firstName": "string",
"code": "number",
"birthday": "DATE",
"address.state": "string",
"address.city": "string",
"address.street": "string"
},
"meetings": {
"_id": "string",
"createdAt": "DATETIME",
"date": "DATE",
"title": "string",
"description": "TEXT"
}
}
}
データベースの指定
同期元のデータベースをsrcに、同期先のデータベースをdistに設定します。
-
"src": "mongodb://localhost:27017/myapp"必ずMongoDBを指定 -
"dist": "mysql://root@localhost:3306/myapp"必ずMySQLを指定
データベースのURLは、次の書式をとります。
-
データベースの種類://ユーザ名:パスワード@サーバ名:ポート/データベース名
コレクション
だいたい、見たままですが、詳しくはAPPENDIXをどうぞ。
MongoDBの下ごしらえ
Momyは、MongoDBのレプリカセットの情報を使います。そのため、standaloneモードのMongoDBだと、リプリケーションができません。次のように、レプリカセットをオンにして起動します。
$ mongod --replSet "rs0" --oplogSize 100
別のターミナルからmongoシェルを開き、レプリカセットを初期化(rs.initiate())しておきます。このコマンドは初回のみ実行してください。これで、レプリカセットがこのデータベースでアクティブになりました。
$ mongo
....
> rs.initiate()
実行する
初回実行時は、--importが必要です。
$ momy --config momyfile.json --import
このオプションをつけると、momyfile.jsonのスキーマの通り、MySQLのテーブルが作成され、MongoDB上の既存ドキュメントが、MySQLにコピーされます。
コピーが完了すると、その後はMongoDBを監視して、リアルタイムにMySQLに同期するようになります。終了する場合は、Ctl+Xを押します。
2回目以降は、
$ momy --config momyfile.json
だけでOKです。サーバなどで、確実に同期を実行し続けたい場合は、foreverがおすすめです。
$ forever momy --config momyfile.json
万が一、momyが落ちた場合も、立ち上げ直して実行を続けてくれます。
最後に
ライブラリ作成の経緯などは、昨年の記事をどうぞ。詳しい使い方についてはMomyのリポジトリも参考にしてください。それでは。
APPENDIX
コレクションの設定
momyfile.json上では、次のような書式で、コレクション名とフィールド設定をします。
{
"コレクション名": {
"_id": "string あるいは number",
"フィールド名1": "フィールドの型",
"フィールド名2": "フィールドの型",
...
}
}
_idは必須。MySQLに持って行く際にプライマリーキーになります。
フィールド名には.を使って、ネストした値を取得することもできます。例:
-
{a:{b:{c: 'Hey!'}}}というデータがあったら、a.b.cで'Hey!'を取得。 -
{address: {state: '東京', city: '世田谷', street: '代田'}}というデータがあったら、address.stateで'東京'を取得。
フィールドの型
型として、次のものが使えます。
BIGINTDOUBLETINYINTVARCHARDATEDATETIMETIMETEXT
メモ: もし、足りない型があったらIssueかPull Requestください。
エイリアスとして、次の表現も使えます。
-
string:VARCHARに同じ -
number:DOUBLEに同じ -
boolean:TINYINTに同じ
日付型
DATE型と、DATETIME型には、"2016-11-13"といった文字列のほか、タイムスタンプ(ミリ秒)を渡すこともできます。もし、DATEが指定されたとすると、MongoDB上の値が次のいずれであっても、MySQLに渡される値は"2016-11-13"となります。
-
"2016-11-13 01:14:28"(文字列) -
"2016-11-13T01:14:28"(文字列) -
"20161113T011428"(文字列) -
1478967268294(数値)
数値型
-
BIGINTを指定した場合、小数点以下はparseInt()で丸められます。 -
DOUBLEを指定した場合、parseFloat()で解釈されます。
文字列型
-
VARCHARは、実際にはVARCHAR(255)です。255文字以上の場合は、トランケートされます。 -
TEXTには、明確な文字数制限がありません。
