sam*_*sam 11 mongodb google-bigquery
将数据从mlab托管的MongoDB导出到google bigquery的最佳方法是什么?
最初,我试图从MongoDB一次加载到BigQuery,后来我正在考虑使用Pub/Sub将实时数据流转换为bigquery.
从mongodb到bigquery的第一次加载我需要帮助.
Qor*_*ani 15
在我看来,最好的做法是建立自己的提取器.这可以使用您选择的语言完成,您可以提取到CSV或JSON.
但是如果你想要快速的方式,如果你的数据不是很大并且可以放在一台服务器中,那么我建议使用mongoexport.假设您有一个简单的文档结构,如下所示:
{
"_id" : "tdfMXH0En5of2rZXSQ2wpzVhZ",
"statuses" : [
{
"status" : "dc9e5511-466c-4146-888a-574918cc2534",
"score" : 53.24388894
}
],
"stored_at" : ISODate("2017-04-12T07:04:23.545Z")
}
Run Code Online (Sandbox Code Playgroud)
然后你需要定义你的BigQuery Schema(mongodb_schema.json),例如:
$ cat > mongodb_schema.json <<EOF
[
{ "name":"_id", "type": "STRING" },
{ "name":"stored_at", "type": "record", "fields": [
{ "name":"date", "type": "STRING" }
]},
{ "name":"statuses", "type": "record", "mode": "repeated", "fields": [
{ "name":"status", "type": "STRING" },
{ "name":"score", "type": "FLOAT" }
]}
]
EOF
Run Code Online (Sandbox Code Playgroud)
现在,有趣的部分开始:-)从MongoDB中提取数据为JSON.假设您有一个具有副本集名称的集群statuses,您的数据库是sample,您的集合是status.
mongoexport \
--host statuses/db-01:27017,db-02:27017,db-03:27017 \
-vv \
--db "sample" \
--collection "status" \
--type "json" \
--limit 100000 \
--out ~/sample.json
Run Code Online (Sandbox Code Playgroud)
正如您在上面所看到的,我将输出限制为100k记录,因为我建议您在为所有数据执行之前运行sample并加载到BigQuery.运行上面的命令之后你应该有你的样本数据sample.json但是有一个字段$date会导致你加载到BigQuery时出错.要解决这个问题,我们可以使用sed它们将它们替换为简单的字段名
# Fix Date field to make it compatible with BQ
sed -i 's/"\$date"/"date"/g' sample.json
Run Code Online (Sandbox Code Playgroud)
现在,您可以压缩,上传到Google云端存储(GCS),然后使用以下命令加载到BigQuery:
# Compress for faster load
gzip sample.json
# Move to GCloud
gsutil mv ./sample.json.gz gs://your-bucket/sample/sample.json.gz
# Load to BQ
bq load \
--source_format=NEWLINE_DELIMITED_JSON \
--max_bad_records=999999 \
--ignore_unknown_values=true \
--encoding=UTF-8 \
--replace \
"YOUR_DATASET.mongodb_sample" \
"gs://your-bucket/sample/*.json.gz" \
"mongodb_schema.json"
Run Code Online (Sandbox Code Playgroud)
如果一切正常,那么返回并--limit 100000从mongoexport命令中删除并再次运行上面的命令来加载所有内容而不是100k样本.
替代解决方案:
如果您想要更多灵活性并且不需要考虑性能,那么您也可以使用mongoCLI工具.这样,您可以在JavaScript中编写提取逻辑并针对您的数据执行它,然后将输出发送到BigQuery.这是我为同一个过程所做的,但是使用JavaScript以CSV格式输出,这样我就可以更轻松地加载BigQuery了:
# Export Logic in JavaScript
cat > export-csv.js <<EOF
var size = 100000;
var maxCount = 1;
for (x = 0; x < maxCount; x = x + 1) {
var recToSkip = x * size;
db.entities.find().skip(recToSkip).limit(size).forEach(function(record) {
var row = record._id + "," + record.stored_at.toISOString();;
record.statuses.forEach(function (l) {
print(row + "," + l.status + "," + l.score)
});
});
}
EOF
# Execute on Mongo CLI
_MONGO_HOSTS="db-01:27017,db-02:27017,db-03:27017/sample?replicaSet=statuses"
mongo --quiet \
"${_MONGO_HOSTS}" \
export-csv.js \
| split -l 500000 --filter='gzip > $FILE.csv.gz' - sample_
# Load all Splitted Files to Google Cloud Storage
gsutil -m mv ./sample_* gs://your-bucket/sample/
# Load files to BigQuery
bq load \
--source_format=CSV \
--max_bad_records=999999 \
--ignore_unknown_values=true \
--encoding=UTF-8 \
--replace \
"YOUR_DATASET.mongodb_sample" \
"gs://your-bucket/sample/sample_*.csv.gz" \
"ID,StoredDate:DATETIME,Status,Score:FLOAT"
Run Code Online (Sandbox Code Playgroud)
提示:在上面的脚本中,我通过管道输出做了一个小技巧,能够将输出拆分为多个带sample_前缀的文件.此外,在分割期间,它将GZip输出,以便您可以更轻松地加载到GCS.