2014-06-13 8 views
5

Próbuję przeczytać zrzut zbiorczy generowane przez mongodump. Plik ma kilka gigabajtów, więc chcę go czytać przyrostowo.Przeczytaj wyjście mongodump z go i mgo

mogę czytać pierwszy obiekt z czymś takim:

buf := make([]byte, 100000) 
f, _ := os.Open(path) 
f.Read(buf) 

var m bson.M 
bson.Unmarshal(buf, &m) 

Jednak nie wiem, ile zostało zużyte buf, więc nie wiem, jak czytać następny.

Czy to możliwe z mgo?

Odpowiedz

2

udało mi się go rozwiązać za pomocą następującego kodu:

for len(buf) > 0 { 
    var r bson.Raw 
    var m userObject 

    bson.Unmarshal(buf, &r) 
    r.Unmarshal(&m) 

    fmt.Println(m) 

    buf = buf[len(r.Data):] 
} 
3

Metoda File.Read zwraca liczbę odczytanych bajtów.

File.Read

Czytaj odczytuje do len (b) bajtów z pliku. Zwraca liczbę odczytanych bajtów i ewentualny błąd. EOF jest sygnalizowane przez liczbę zerową z err ustawionym na io.EOF.

Więc można uzyskać liczbę bajtów odczytanych po prostu przechowywanie parametrów powrotów was czytać:

n, err := f.Read(buf) 
4

Korzystanie MgO na bson.Unmarshal() nie wystarcza - że funkcja ma za zadanie zająć []byte reprezentujących jeden dokument i odrzuć go do wartości.

Będziesz potrzebować funkcji, która odczyta następny cały dokument z pliku zrzutu, a następnie możesz przekazać wynik do bson.Unmarshal().

Porównując to do encoding/json lub encoding/gob byłoby wygodne, jeśli mgo.bson miał Reader rodzaju spożytego dokumentów z io.Reader.

W każdym razie, z pliku source for mongodump, wygląda na to, że plik zrzutu jest tylko serią dokumentów, bez plików nagłówkowych/stopek lub jawnych separatorów rekordów.

BSONTool::processFile pokazuje, w jaki sposób magazyn mongore czyta plik zrzutu. Ich kod odczytuje 4 bajty w celu określenia długości dokumentu, a następnie wykorzystuje ten rozmiar do odczytania reszty dokumentu. Potwierdzono, że prefiks rozmiaru jest częścią bson spec.

Oto playground example, który pokazuje, w jaki sposób można to zrobić w Go: przeczytaj pole długości, przeczytaj resztę dokumentu, niegłośny, powtórz.

+0

Tak, potrzebujemy 'bson.NewDecoder (...)' idealnie, w tym przypadku użycia. –

0

Niks Keets' answer nie działa dla mnie. W jakiś sposób len(r.Data) była zawsze całą długością bufora. Więc wyszedłem z tego innego kodu:

for len(buff) > 0 { 
    messageSize := binary.LittleEndian.Uint32(buff) 
    err = bson.Unmarshal(buff, &myObject) 
    if err != nil { 
     panic(err) 
    } 

    // Do your stuff 

    buff = buff[messageSize:] 
} 

Oczywiście trzeba obsłużyć skrócone strucs przy czym bufora. W moim przypadku mógłbym załadować cały plik do pamięci.