2017-02-10 40 views
6

什么是出口数据从托管的MongoDB在MLAB到Google BigQuery中的最佳方式是什么?MongoDB的BigQuery的

起初,我试图做的MongoDB从一次加载至BigQuery,后来我想使用的Pub/Sub实时数据流至BigQuery的。

我需要从MongoDB的第一次加载到BigQuery的帮助。

回答

2

从MongoDB的文档的基本的阅读,这听起来像你可以使用mongoexport转储数据库如JSON。完成之后,请参阅BigQuery loading data主题,以获取有关如何在将它们复制到GCS后从JSON文件创建表的说明。

+0

日期字段怎么样?当我将数据导出到日期/时间字段时显示为“$ date”,这对于BigQuery字段名称不可接受。有没有解决方法? – Qorbani

+0

我认为你不得不首先重新命名它们。 –

+0

谢谢埃利奥特,我找到了解决这个问题的方法,并将其作为解决这个问题的另一个答案,以后可能会帮助像我这样的人:-) – Qorbani

7

在我看来,最好的做法是建立自己的提取。这可以用您选择的语言完成,并且您可以解压缩为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。