表題のことをするためのライブラリ「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
で'東京'を取得。
フィールドの型
型として、次のものが使えます。
BIGINT
DOUBLE
TINYINT
VARCHAR
DATE
DATETIME
TIME
TEXT
メモ: もし、足りない型があったら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
には、明確な文字数制限がありません。