Mongodb嵌套数组转MySQL

因为目标站点返回的数据是json格式,一方面为了学习新知识,另一方面是想偷个懒,所以直接使用Mongdb保存爬虫结果。
最近有个新需求:使用Data-V对这些存量数据制作数据大屏,但目前Data-V支持的数据库只有关系型数据库(当然也可以写API来给Data-V投喂数据,但是如此好像更麻烦些),因此需要将数据从Mongodb 迁移到 MySQL。
最朴素的想法,当然是用Python写一段脚本,从Mongodb读取需求的字段,然后再逐条插入MySQL中。这个方法肯定可以获得预期的效果,预计100行以内的代码都能完成。但是,MongoDB和MySQL既然已经是很成熟的产品了,对数据迁移应该有更好的解决方案,自己再造一遍轮子实在不是个好主意。

寻找新方法

之前查看MongoDB的根目录mongodb安装路径\bin发现有一个叫做mongoexport.exe的文件,第一眼就觉得是想要找的功能。

> mongoexport.exe --help
> Usage:
  mongoexport <options>

Export data from MongoDB in CSV or JSON format.

See http://docs.mongodb.org/manual/reference/program/mongoexport/ for more information.

利用这个工具可以将查询结果导出为CSV或者JSON格式,MySQL的数据导入工具刚好可以直接导入以上两种格式的数据。看来这应该就是我们需要的路径了。
mongoexport.exe的参数挺多,按照上一段代码的方法可以仔细查看,我使用的几个参数如下:

> mongoexport.exe /uri:mongodb://username:password@host:port/database /c collection /f field /o resultPATH /jsonArray
/uri 导出数据的mongodb的uri,username填用户名,password密码,host IP, port 端口,database 验证用户名、密码的数据库。
/c 想要导出的Collections
/f 需要导出的字段
/o 导出文件的路径及文件名
/jsonArray 导出json数组而非jsonline

如果需要查询,可以使用 \q参数输入查询语句。接下来,使用MySQL的文件导入工具即可将数据导入到MySQL中,速度还是挺有保障的。
这种方法针对形如{ "_id" : 0, "nref_date" : "20190318-20190416", "nname" : "未知", "nvalue" : 1 }的数据是比较有效的,但涉及到拥有嵌套数组的数据就显得有些难以处理了。
例如:

image.png

如何将上图中list[0]的item_list中的5对(key, value)添加ref_date存储成MySQL中的5条记录?

新的挑战

之前看文档的时候了解到,MongoDB有聚合操作(aggregate),也支持管道(pipeline)操作。将数组解包使用的是"$unwind"操作,嵌套的数组用点号分隔即可,还是先回顾下常用的一些聚合操作吧:

$project:修改输入文档结构,可用来新增、删除域,或者构建新结果。
$match:输出符合条件的文档,可以用来过滤树。
$limit:用来限制管道返回的文档数。
$skip:在聚合管道中跳过指定数量的文档。
$unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
$group:将集合中的文档分组。
$sort:排序。
$out:将管道聚合操作返回的结果另存成一个collections,必须位于管道的最后一个操作。

本例中可以使用将list.item_list解包,注意因为list也是数组,所以使用了两次$unwind:

db.collections.aggregate([{"$unwind": "$list"}, {"$unwind": "$list.item_list"})

执行过后,得到如下形状的5个文档:

{
    "_id" : ObjectId("5cb595a2923d072acc8bdf8b"),
    "ref_date" : "20181129",
    "list" : {
        "index" : "access_source_session_cnt",
        "item_list" : {
            "key" : 36,
            "value" : 19
        }
    }
}

但输出的形式,和我们想要的结果还不太一样,如果直接使用MySQL的导入工具还是无法找到对应字段的映射关系。
接下来使用$project修改返回文档的结构,直接在上面的管道中新增

db.collections.aggregate([{"$unwind": "$list"}, {"$unwind": "$list.item_list"}, {"$project": {"newkey": "$list.item_list.key", "newvalue": "$list.item_list.value", "new_ref_date": "$ref_date"}}])

输出的第一个元素变成以下结构:

{
    "_id" : ObjectId("5cb595a2923d072acc8bdf8b"),
    "newkey" : 29,
    "newvalue" : 17,
    "new_ref_date" : "20181129"
}

如果使用的MongoDB支持将查询结果导出成JSON,那到这里已经可以完成任务了!遗憾的是我用的Robot 3T貌似并不支持,不过也没有关系,我们使用$out操作符将管道的聚合结果另存成一个Collections即可。
最终的管道聚合操作有四步操作:

db.collections.aggregate([
{"$unwind": "$list"}, 
{"$unwind": "$list.item_list"}, 
{"$project": {"newkey": "$list.item_list.key", "newvalue": "$list.item_list.value", "new_ref_date": "$ref_date"}},
{"$out": "outputjson"}
])

接下来使用mongoexport.exe工具将outputjson导出成JSON格式即可导入MySQL了!

MongoDB多层嵌套脑壳疼、查个文档又尽是英文、阿里云Data-v居然都不支持,以后不会再用了!!!
卧槽原来可以这样!
真香!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容

  • NoSQL 的全称是 Not Only SQL,也可以理解非关系型的数据库,是一种新型的革命式的数据库设计方式,不...
    tianjianlong阅读 3,983评论 1 25
  • 什么是Mongodb数据库? MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统 Mo...
    瘦不下去了阅读 667评论 0 0
  • NoSQL 的全称是 Not Only SQL,也可以理解非关系型的数据库,是一种新型的革命式的数据库设计方式,不...
    梅花九弄丶阅读 10,642评论 1 5
  • 一、MongoDB简介 概述MongoDB是一个基于分布式文件存储的数据库,由C++语言编写。旨在为WEB应用提供...
    慕杨_阅读 551评论 0 4
  • 1. MongoDB 简介 MongoDB是一个可扩展的高性能,开源,模式自由,面向文档的NoSQL,基于分布式文...
    rhlp阅读 1,101评论 0 3