摘要:則在讀取數據時將兩個中文字段混淆成了一個字段,導致整個數據結構錯亂。三條路子全軍覆沒,這讓我情何以堪,好在使用的經驗頗豐,通過中文的轉換和切割就輕松解決了這個問題。
概述
在現實場景中,由于數據來源的異構,數據源的格式往往是難以統一的,這就導致大量具有價值的數據通常是以非結構化的形式聚合在一起的。對于這些非結構化數據,最常見的數據結構就是JSON,而對應的數據庫就是MongoDB。
利用MongoDB這樣的NoSQL數據庫,我們可以把異構的數據源整合到若干個collection中,通過key-value的形式對數據進行增刪改查。雖然MongoDB在數據聚合上有天然的優勢,但是在事務處理(OLTP)與數據分析(OLAP)上的表現卻不盡人意。由于MongoDB自身是一個文檔型數據庫,一方面,MongoDB 并沒有事務的概念,所以在需要保證數據一致性的場景下并不好用。另一方面,MongoDB的join查詢也沒有RDBMS來得直觀方便,所以在需要多表關聯查詢的場景下也非常捉急。
通常,對于小數據集,我們都會將數據導入到類似MySQL這樣的RDBMS中做進一步的結構化處理,對于大數據集則可以通過Hive導入到HDFS上。那么,將MongoDB的非結構化數據導入到RDBMS中的最優方案又是什么呢?本文將對非結構化數據與結構化數據的管道構建做詳細的討論。
從 Mongo 到 MySQL iPython從Mongo遷移數據到MySQL,我的第一個反應是應該寫個腳本,我首先想到了用Python從Mongo讀取數據到內存中然后再批量寫入MySQL。
這里,我選擇了使用pymongo。
%% bash pip install pymongo # 這里不需要安裝 Mongo的client
首先是讀取Mongo數據
from pymongo import MongoClient client = MongoClient("192.168.1.100", 27017) db = client["tesedb"] posts = db.test_collection condition = {"_id":"harryzhu"} result_set = posts.find(condition) for i in result_set: print(i)
這里由于python會有中文的問題,我自己定義了一個將unicode轉為utf-8的函數:
def getMongoData(data,field): if data[field] is None: return("") else: if isinstance(data[field], unicode): return(data[field].encode("utf-8")) else: return(data[field])
接著,準備往MySQL中導入數據
%% bash pip install MySQL-python # 這里需要安裝 MySQL的client
import MySQLdb db = MySQLdb.connect("192.168.1.100","root","harryzhu","testdb" ) cursor = db.cursor() values = r"("{id}","{value}","{datetime}","{stock_code}","{share}")".format(id=getMongoData(i,"_id"),value=getMongoData(i,"value"),datetime=getMongoData(i,"datetime"),stock_code=getMongoData(i,"stock_code"),share=getMongoData(i,"share")) sql = r"INSERT INTO `FinanceR` (`id`,`value`,`datetime`,`stock_code`,`share`) VALUES " + values try: cursor.execute(sql) db.commit() except: db.rollback() db.close()
從Mongo中讀取的JSON需要在這里拼接SQL語句是一件用戶體驗非常糟糕的事情,如果有更好的方法歡迎在留言區討論。在嘗試拼接sql 2個小時后,我果斷放棄了用Python導數據的想法。
R由于拼接SQL是非常蛋疼的一件事情,我想到了利用R中的data frame直接完成數據的插入黑魔法。
首先,同樣是需要將數據從Mongo中讀取出來.在嘗試使用RMongo,rmongodb以及mongolite之后,我依然選擇了比較古老的RMongo。在使用的過程中,這三個包都有各自的問題。
rmongodb的教程含糊不清,看了很久都沒有找到調用遠程mongo數據庫的case,而出于jeroenooms大人之手的后起之秀mongolite則在導入數據的時候果斷的丟失了非常關鍵的_id字段,在安裝最新包之后會出現jsonlite依賴包的異常。RMongo則在讀取數據時將兩個中文字段混淆成了一個字段,導致整個數據結構錯亂。
三條路子全軍覆沒,這讓我情何以堪,好在使用R的經驗頗豐,通過中文的轉換和切割就輕松解決了這個問題。
下面演示一下如何使用RMongo解決Mongo數據的讀取:
install.packages("RMongo")
Sys.setenv("JAVA_HOME"="/usr/bin/java") library(RMongo) # 這里不需要安裝 Mongo的client library(dplyr) # 設置數據庫 FinanceR <- RMongo::mongoDbConnect(host="192.168.1.100") dbShowCollections(FinanceR) # 設置查詢語句 condition = "{}" # 得到返回結果 output <- RMongo::dbGetQuery(FinanceR, collection="portfolio_20160619", condition, skip=0, limit=2) input <- output %>% dplyr::mutate(stock_name1 = iconv(strsplit(iconv(stock_name,from = "utf-8", to = "gbk"),"100")[[1]][1],from = "gbk",to = "utf-8"))%>% dplyr::mutate(portfolio_name = iconv(strsplit(iconv(stock_name,from = "utf-8", to = "gbk"),"100")[[1]][2],from = "gbk",to = "utf-8"))%>% dplyr::select(-stock_name)%>% rbind(cum_value="",risk="") dbDisconnect(FinanceR)
現在,我們已經把Mongo中的數據成功導入到了內存中,下面將講解如何使用黑魔法直接將整個data frame壓入數據庫。
install.packages("RMySQL")
library(RMySQL) # 這里不需要安裝 MySQL的client con <- RMySQL::dbConnect(RMySQL::MySQL(), user="FinanceR", password="FinanceR", dbname="FinanceR", host="192.168.1.100") # 選擇追加,而不是重寫的方式來添加數據,否則數據庫的schema會被重寫 RMySQL::dbWriteTable(con,input,row.names = FASLE, overwrite = FALSE, append = TRUE) on.exit(dbDisconnect(con))Shell
Python 和 R 的方式各有利弊,對于Python而言目前簡單粗暴的方式就是SQL拼接,而R則在流水化上比較困難。所以最后轉向尋求Shell命令的方式,通過調用 Mongo client 和 MySQL client 的 API 來完成整個數據的轉化操作。
經過研究發現 Mongo Client 提供了將數據轉成 csv 格式的接口,之后mysql則通過load命令可以將數據加載到數據庫中。
結論通過將非結構化數據轉化為 data frame 后直接壓入 RDBMS,一方面省去了枯燥的SQL拼接,一方面操作又直觀清晰不易出錯,對于小數據集合,直接用這樣的方法增量導入數據不失為一種好方法,對于批量數據的流水化則采用Shell腳本調用Mongo和MySQL客戶端命令較為合適。
參考資料Python MySQL Database Access
R client to interface with MongoDB
python+mongoDB+pymongo常見命令及簡單案例
更優閱讀體驗可直接訪問原文地址:https://segmentfault.com/a/1190000005750424
作為分享主義者(sharism),本人所有互聯網發布的圖文均遵從CC版權,轉載請保留作者信息并注明作者 Harry Zhu 的 FinanceR專欄:https://segmentfault.com/blog/harryprince,如果涉及源代碼請注明GitHub地址:https://github.com/harryprince。微信號: harryzhustudio
商業使用請聯系作者。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/38018.html
摘要:概述在真實的數據科學世界里,我們會有兩個極端,一個是業務,一個是工程。偏向業務的數據科學被稱為數據分析,也就是型數據科學。所以說,同時學會和這兩把刷子才是數據科學的王道。 showImg(https://segmentfault.com/img/bVAgki?w=980&h=596); 概述 在真實的數據科學世界里,我們會有兩個極端,一個是業務,一個是工程。偏向業務的數據科學被稱為數據...
摘要:對于異常機制的合理運用是直接關系到碼農飯碗的事情所以,本文將具體介紹一下和的異常處理機制,闡明二者在異常處理機制上的異同。下面將具體介紹二者的異常處理機制。 概述 showImg(https://segmentfault.com/img/remote/1460000006760426); 異常處理,是編程語言或計算機硬件里的一種機制,用于處理軟件或信息系統中出現的異常狀況(即超出程序正...
摘要:概述工欲善其事必先利其器,如果現在要評選數據科學中最好用的編輯器注意一定是可以通過訪問的,和一定是角逐的最大熱門,正確使用編輯器可以很大地提升我們的工作效率。 概述 showImg(https://segmentfault.com/img/bVAdol); 工欲善其事必先利其器,如果現在要評選數據科學中最好用的Web 編輯器(注意一定是可以通過Web訪問的),RStudio和Jupyt...
摘要:另外一個我們同時使用兩種語言的原因是已有的統計學工具與包。對另一些為讀者寫數據科學工具的人來說他們從一開始就考慮了這些跨語言。和實際上是用實現的這是條阻力最小的路徑。無論是哪個贏得這場語言戰爭,和都將保持在數據科學屆的地位。 showImg(https://segmentfault.com/img/remote/1460000006762469); 概述 幾周前,我有幸在 Scipy ...
摘要:然而,它最終變成了一種昂貴的選擇,并不總是具有最新的統計功能。對于大多數專業人士而言,這是昂貴的且沒有能力以個人身份購買。 showImg(https://segmentfault.com/img/remote/1460000019466629); 介紹 我們熱衷于比較! 從智能手機中的三星,蘋果和HTC,移動操作系統中的iOS,Android和Windows,到即將進行選舉的候選人的...
閱讀 1161·2021-11-16 11:45
閱讀 1016·2021-09-04 16:41
閱讀 3077·2019-08-29 16:40
閱讀 2852·2019-08-29 15:34
閱讀 2673·2019-08-29 13:11
閱讀 1734·2019-08-29 12:58
閱讀 1726·2019-08-28 18:00
閱讀 1776·2019-08-26 18:26