Theo ý kiến của tôi, cách tốt nhất là tạo bộ giải nén của riêng bạn. Điều đó có thể được thực hiện bằng ngôn ngữ bạn chọn và bạn có thể trích xuất sang CSV hoặc JSON.
Nhưng nếu bạn đang tìm kiếm một cách nhanh chóng và nếu dữ liệu của bạn không lớn và có thể vừa với một máy chủ thì tôi khuyên bạn nên sử dụng mongoexport
. Giả sử bạn có một cấu trúc tài liệu đơn giản như dưới đây:
{
"_id" : "tdfMXH0En5of2rZXSQ2wpzVhZ",
"statuses" : [
{
"status" : "dc9e5511-466c-4146-888a-574918cc2534",
"score" : 53.24388894
}
],
"stored_at" : ISODate("2017-04-12T07:04:23.545Z")
}
Sau đó, bạn cần phải xác định BigQuery Schema của bạn (mongodb_schema.json
) như:
$ 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
Bây giờ, phần thú vị bắt đầu :-) Extracting dữ liệu dưới dạng JSON từ MongoDB của bạn. Giả sử bạn có một cụm với tên bộ bản sao statuses
, db của bạn là sample
và bộ sưu tập của bạn là 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
Như bạn có thể thấy ở trên, tôi giới hạn bạn chạy mẫu và tải lên BigQuery trước khi thực hiện cho tất cả dữ liệu của bạn. Sau khi chạy lệnh trên, bạn sẽ có dữ liệu mẫu của mình trong sample.json
NHƯNG có một trường $date
sẽ khiến bạn tải lỗi lên BigQuery. Để khắc phục điều đó chúng ta có thể sử dụng sed
để thay thế họ tên trường đơn giản:
# Fix Date field to make it compatible with BQ
sed -i 's/"\$date"/"date"/g' sample.json
Bây giờ bạn có thể nén, tải lên Google Cloud Storage (GCS) và sau đó tải để BigQuery sử dụng lệnh sau:
# 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"
Nếu mọi thứ đều ổn, sau đó quay lại và xóa --limit 100000
từ mongoexport
lệnh và chạy lại các lệnh trên một lần nữa để tải mọi thứ thay vì mẫu 100k.
THAY THẾ SOLUTION:
Nếu bạn muốn biết thêm tính linh hoạt và hiệu suất không phải là mối quan tâm của bạn, sau đó bạn có thể sử dụng công cụ mongo
CLI là tốt. Bằng cách này, bạn có thể viết logic trích xuất của mình trong JavaScript và thực thi nó dựa trên dữ liệu của bạn và sau đó gửi đầu ra tới BigQuery. Dưới đây là những gì tôi đã làm cho quá trình tương tự nhưng sử dụng Javascript để đầu ra trong CSV để tôi có thể tải nó dễ dàng hơn để 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"
TIP: Trong kịch bản ở trên tôi đã lừa nhỏ bằng đường ống đầu ra để có thể chia đầu ra thành nhiều tệp với tiền tố sample_
. Ngoài ra trong quá trình chia, nó sẽ GZip đầu ra để bạn có thể tải nó dễ dàng hơn với GCS.
Làm thế nào về trường Ngày? Khi tôi xuất dữ liệu sang trường ngày/giờ hiển thị như "$ date" không được chấp nhận cho tên trường BigQuery. Có cách giải quyết nào cho vấn đề này không? – Qorbani
Tôi nghĩ bạn sẽ cần phải đổi tên chúng bằng cách nào đó đầu tiên, thật không may. –
Cảm ơn bạn Elliott, tôi tìm cách sửa lỗi và gửi nó như một câu trả lời khác cho câu hỏi này có thể giúp một người như tôi trong tương lai :-) – Qorbani