妈妈:使用MySQL在Mongo的视图上是可以的
最近,重新思考(或者说大约3周之后),DB混合使用会不会更好的话,也有些许传闻。不管那些高尚的谈话如何,这个Mongo开始的SQLer项目是出于「精神健康」(或者说为了精神健康)、「在紧急情况下也能使用SQL」之类的心态而创建的。
如果只想查看代码,请访问Momy存储库。
首先
有几个动机对于MongoDB来说是重要的
-
- がしがし集計したい
-
- さくっとテーブル間のJOINをしたい
- Microsoft Accessや、Libre Office Baseから接続したい
在考虑MEAN(指MongoDB、Express.js、AngularJS和Node.js的开发技术堆栈)或SPA(单页应用)等情境时,尽管这是一种常见情况,但实际上相当麻烦。尤其是最后一项,更是个意外的难点。
注1: ここでは、一応、MongoDB→MySQL同期の方向に話を持って行きますが、もっといい方法があったら是非教えてください。
注2: ちなみにMEANの「A」はanythingの略ですよ?
寻找解决方案
ODBC是什么?
虽然有一个初步的开放选项存在,但由于它仍然处于“实验性”的状态已经过去了三年,所以仅供参考。嗯,哎呀,如果用MySQL的话就可以简单连接了……但是直接连接到NoSQL可能有些困难。
sp13_10g – mongoDb ODBC Driver EXPERIMENTAL
商用的话,从这里或者那里似乎也有可用的驱动程序,但是不要过多追问,因为它们可能很贵。
莫SQL?
Stripe发布了一个名为”MoSQL”的开源工具。这是一个可以直接将MongoDB与SQL进行同步的工具,它是用Ruby编写的。GitHub上的星标大约有1K。然而,它仅支持PostgreSQL。虽然一度有将其扩展至支持MySQL的动向,但似乎最终没有实现。遗憾。
- https://github.com/stripe/mosql
尽管如此,在能够转向PostgreSQL的情况下,这是一个选择。在MEAN的背景下,确实很难处理…
然而,如果可以转向PostgreSQL,那是一个选项。在MEAN的环境下,确实不容易处理…
在Node的世界里不存在吗?
我在这里看了那么多候选人,但还差一步。不知道有没有什么办法可以在Node的世界中解决呢?我试着仔细搜寻,找到了一些看起来不错的东西。这…这难道就是正确的答案吗?
- MongoDB-to-MySQL
尽管在npm上也发布了,但它总是给人一种没有完成的感觉。事实上,当我尝试使用它时…它根本无法运行,让我非常苦恼。看来,它也停留在”三年前”,大家已经对Mongo感到厌倦了…这让我感受到了历史的沉重。
没办法,只能靠我自己了。
当时虽然迷茫不解,但是只要阅读代码,不管是MoSQL还是MongoDB-to-MySQL,它们所做的事情都很简单。
-
- MongoDB間のReplication機能をうまく流用する
-
- Tailable Cursor(追尾カーソル?)でMongoDBの変更を監視
- 変更箇所のログを取ってきて、SQLなデータベースに反映
这些东西,大部分都可以通过MongoDB本身的功能来解决。如果只是这些需求的话,我觉得我可以做出来。
妈妈
我做了。
最初,我们打算对MongoDB-to-MySQL进行修改,但是最终几乎没有原始代码留下,所以我们决定给它取了一个别名。现在它叫做Mongo to MySQL,简称为”Momy”。据说在法国有一个地方叫这个名字。
利用副本套装的日志
核心代码是以下部分吗?(稍微变形)
tail () {
const
filters = {
// 前回のタイムスタンプより新しいログを監視
ts: { $gt: Timestamp.fromNumber(ts) }
},
curOpts = {
// 追尾モードを設定
tailable: true,
awaitdata: true
}
mongodb.connect(url)
.then(db => {
db.collection('oplog.rs')
.find(filters, curOpts)
// 検索結果はストリームとして取得
.stream()
.on('data', log => { /* MySQLに保存 */ })
})
}
在MongoDB中进行复制相关设置时,会添加一个名为local的数据库(在独立使用时不存在,有时在GUI应用中会被隐藏)。
最新的MongoDB通常使用副本集(replica set)实现多台服务器之间的复制和故障转移。本来用于MongoDB之间同步的日志信息会保存在之前提到的local内的oplog.rs集合中。通过监视并提取它作为流,就可以得到前面展示的这样的代码。太方便了。MongoDB的API真是太方便了。
数据库的准备工作 de
首先,让我们启动一个空的mongod。在此过程中,加入–replSet和–oplogSize选项。前者类似于复制集的“组名”,后者用于设置日志的大小(以MB为单位)。
注: すでに手元で運用中のmongodがある場合は、別ポート–portかつ別ディレクトリ–dbpathにしたほうが良いかもしれません。
$ mongod --replSet "rs0" --oplogSize 100
在另一个窗口中打开终端,启动mongo shell。
$ mongo
....
> rs.initiate()
如此一来,当执行rs.initiate()命令时,将生成所需的数据库和集合。
接下来,按照平时的方式/照常进行。
-
- MongoDB: アプリケーション用のデータベースを作成
- MySQL: 受入れ用のデータベースを作成
只要准备好就行了。数据库名称可以任意,但在接下来的说明中,我们都使用”myapp”。
一种基于模式的东西
可以复制MongoDB上的所有字段,但也可以选择只保留“必要的部分”。可以考虑“只导入用于统计的数值,跳过备注栏等”等方法。
即使是无模式的NoSQL,实际上在应用程序中应该具有一定的结构。限定主要项目和必要的分析项目,可以避免频繁跟随MongoDB的模式变更,更现实可行。从思考的角度来看,
-
- ドキュメント (帳票データとか) – MongoDB
- メタデータ (共通項目、集計項目) – MySQL
如果我们这样说会更容易理解吗?我们可以将前者比作“文件”,将后者比作“文件系统”。
在Mommy中,您需要准备以下类型的json文件,并定义模式。建议文件名为momyfile.json。
{
"src": "mongodb://localhost:27017/myapp",
"dist": "mysql://root@localhost:3306/myapp",
"prefix": "t_",
"collections": {
"collection1": {
"_id": "number",
"field1": "number",
"field2": "string",
"field3": "boolean"
},
"collection2": {
"_id": "number",
"field1": "number",
"field2": "string",
"field3": "boolean"
}
}
}
src: MongoDBサーバのURL
dist: MySQLサーバのURL
prefix: MySQLのデータベース名に共通の接頭辞をつけたい場合に設定 (省略可)
collections: 同期するコレクションごとのフィールド定義
在字段定义中,我们简单地指定了数字(number)、字符串(string)和布尔值(boolean)。
"<コレクション名>": {
"<フィールド名>": "<フィールド型>"
}
试着动一下
请从npm进行安装。
$ npm install -g momy
假设MongoDB服务器已经包含了某种数据。在首次执行时,我们将先导入这些数据,然后开始进行监视。请指定 “–import” 选项。
$ momy --config momyfile.json --import
如果数据数量较大,可能会需要一些时间。我们需要确认MySQL端是否已经复制了数据。停止时,请使用Ctrl + C。之后,应该只需要差异数据,不需要使用任何选项。
$ momy --config momyfile.json
或者也可以使用“永远”这个词。
$ forever momy --config momyfile.json
注: –configオプションを外すと、ワーキングディレクトリのmomyfile.jsonを使います。
用中文翻译以下内容,仅需一个选项:
通过API
大概我会把它设计成可以通过API使用的。
总结
BaaSが当たり前になっていく中、こうやってデータベースで遊べるのもあと数年の話でしょうか。はやくRelay的な世界に移行しますように。
とはいえ、現場レベルだとMicrosoft Accessはまだ幅を利かせているので、そこからBaaSにどうやって繋げるの? とかはまだ不透明だったりします。ログの解析ツールはオンラインで色々ありますが、社内での解析方法自体が秘伝のタレ化し、オンライン化不可能案件になっていることもしばしば。ビッグデータになったとたん、Accessだとどうしようもなくなるという話はそれはそれ。
使用Aggregation Framework来操作和分析MongoDB数据也逐渐改进了很多,掌握这个技能是很重要的。
-
- SQL慣れしているほど、覚えるのがめんどくさい
- 多機能になった集計機能(aggregation)をどのようにAPIに晒すか
有时候我会这样考虑。后一个问题相当复杂。
-
- 定型の集計以外
- 設計時には想定外のテーブルと複雑にJOINさせつつ、傾向を探るとか
我不太清楚该如何通过API来解决这个问题,没有很明确的落脚点。
在这种情况下,在找到答案之前,我的主要功能是使用MongoDB灵活地构建,用于聚合等后台操作,则放置一个只读的MySQL(或其他RDS)是合理的想法。