2017-02-10 21 views
6

Jaki jest najlepszy sposób na eksport danych z MongoDB hostowanych w mlab do BigQuery Google?MongoDB do BigQuery

Początkowo próbuję wykonać jednorazowe ładowanie z MongoDB do BigQuery, a później myślę o używaniu Pub/Sub do przepływu danych w czasie rzeczywistym do bigquery.

Potrzebuję pomocy przy pierwszym ładowaniu od mongotb do bigquery.

Odpowiedz

2

Z podstawowego czytania dokumentacji MongoDB wynika, że ​​można użyć mongoexport, aby zrzucić bazę danych jako JSON. Gdy to zrobisz, zapoznaj się z tematem BigQuery loading data, aby uzyskać opis tworzenia tabeli z plików JSON po skopiowaniu ich do GCS.

+0

Co z polami dat? Po wyeksportowaniu danych do pola data/czas pojawia się "data", co jest niedopuszczalne w przypadku nazw pól BigQuery. Czy istnieje jakieś obejście tego problemu? – Qorbani

+0

Myślę, że najpierw trzeba będzie zmienić ich nazwy, niestety. –

+0

Dziękuję Elliott, znajduję sposób, aby to naprawić, a także przesłać go jako kolejną odpowiedź na to pytanie, które może pomóc komuś jak ja w przyszłości :-) – Qorbani

7

Moim zdaniem najlepszą praktyką jest budowa własnego ekstraktora. Można to zrobić za pomocą wybranego języka i można wyodrębnić do pliku CSV lub JSON.

Ale jeśli szukasz szybko i jeśli Twoje dane nie są duże i mieszczą się na jednym serwerze, to polecam użyć mongoexport. Załóżmy, że masz prostą strukturę dokumentu, takiego jak poniżej:

{ 
    "_id" : "tdfMXH0En5of2rZXSQ2wpzVhZ", 
    "statuses" : [ 
     { 
      "status" : "dc9e5511-466c-4146-888a-574918cc2534", 
      "score" : 53.24388894 
     } 
    ], 
    "stored_at" : ISODate("2017-04-12T07:04:23.545Z") 
} 

Następnie trzeba zdefiniować BigQuery Schema (mongodb_schema.json), takie jak:

$ 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 

Teraz zaczyna się zabawa :-) Wyodrębnianie dane jako JSON z twojego MongoDB. Załóżmy, że masz klaster z zestawem replik o nazwie statuses. Twoja db to sample, a Twoja kolekcja to 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 

Jak widać powyżej, ograniczę wyjście do 100k rekordów dlatego polecam uruchomieniu próbki i obciążenia do BigQuery przed robi to dla wszystkich swoich danych. Po uruchomieniu powyższego polecenia powinieneś mieć dane przykładowe w sample.json, ale istnieje pole $date, które spowoduje błąd podczas ładowania do BigQuery. Aby ustalić, które możemy wykorzystać sed zastąpić je do prostego Nazwa pola:

# Fix Date field to make it compatible with BQ 
sed -i 's/"\$date"/"date"/g' sample.json 

Teraz można skompresować, przesłać do Google Cloud Storage (GCS), a następnie załadować do BigQuery za pomocą następujących poleceń:

# 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" 

Jeśli wszystko było w porządku, wróć i usuń polecenie --limit 100000 z polecenia mongoexport i ponownie uruchom powyższe polecenia, aby załadować wszystko zamiast próbki 100k.

ALTERNATYWNE ROZWIĄZANIE:

Jeśli chcesz większą elastyczność i wydajność nie jest twoja sprawa, a następnie można użyć mongo CLI narzędzia, jak również. W ten sposób możesz napisać logikę wyodrębniania w JavaScript i wykonać ją w oparciu o dane, a następnie wysłać wyniki do BigQuery. Oto co zrobiłem dla tego samego procesu, ale używane JavaScript na wyjście w formacie CSV, więc mogę załadować go znacznie łatwiej 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: W powyższym skrypcie zrobiłem mały trik przez potokiem wyjście na stanie podziel dane wyjściowe na wiele plików z prefiksem sample_. Również podczas dzielenia będzie GZip wyjście, dzięki czemu można go łatwiej załadować do GCS.