什么是出口数据从托管的MongoDB在MLAB到Google BigQuery中的最佳方式是什么?MongoDB的BigQuery的
起初,我试图做的MongoDB从一次加载至BigQuery,后来我想使用的Pub/Sub实时数据流至BigQuery的。
我需要从MongoDB的第一次加载到BigQuery的帮助。
什么是出口数据从托管的MongoDB在MLAB到Google BigQuery中的最佳方式是什么?MongoDB的BigQuery的
起初,我试图做的MongoDB从一次加载至BigQuery,后来我想使用的Pub/Sub实时数据流至BigQuery的。
我需要从MongoDB的第一次加载到BigQuery的帮助。
从MongoDB的文档的基本的阅读,这听起来像你可以使用mongoexport
转储数据库如JSON。完成之后,请参阅BigQuery loading data主题,以获取有关如何在将它们复制到GCS后从JSON文件创建表的说明。
在我看来,最好的做法是建立自己的提取。这可以用您选择的语言完成,并且您可以解压缩为CSV或JSON。
但是,如果你寻找一个快速的方式,如果你的数据不是巨大的,可以在一个服务器内适合的话,我建议使用mongoexport
。让我们假设你有一个简单的文件结构,如下图所示:
{
"_id" : "tdfMXH0En5of2rZXSQ2wpzVhZ",
"statuses" : [
{
"status" : "dc9e5511-466c-4146-888a-574918cc2534",
"score" : 53.24388894
}
],
"stored_at" : ISODate("2017-04-12T07:04:23.545Z")
}
然后,你需要定义你的BigQuery架构(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
现在,有趣的部分开始提取:-)数据为来自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
正如你可以在上面看到的,我将输出限制为100K记录,因为我建议你做它的所有数据之前运行的样品和负载至BigQuery。运行上面的命令后,你应该有你的样本数据sample.json
但有一个字段$date
这将导致您加载到BigQuery时出错。为了解决这个问题,我们可以使用sed
将其替换,以简单的字段名:
# Fix Date field to make it compatible with BQ
sed -i 's/"\$date"/"date"/g' sample.json
现在你可以压缩,上传到谷歌云存储(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"
如果一切正常,则返回并从mongoexport
命令中删除--limit 100000
命令,并再次运行上述命令以加载所有内容,而不是100k样本。
替代解决方案:
如果你想要更多的灵活性和性能是不是你的关心,那么你可以使用mongo
CLI工具为好。通过这种方式,您可以将提取逻辑写入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"
提示:在上面的脚本中,我做了个小窍门通过管道输出到能够用sample_
前缀将输出分成多个文件。另外在分割期间,它将GZip输出,所以你可以更容易地加载到GCS。
日期字段怎么样?当我将数据导出到日期/时间字段时显示为“$ date”,这对于BigQuery字段名称不可接受。有没有解决方法? – Qorbani
我认为你不得不首先重新命名它们。 –
谢谢埃利奥特,我找到了解决这个问题的方法,并将其作为解决这个问题的另一个答案,以后可能会帮助像我这样的人:-) – Qorbani