2012-08-08 6 views
16

Mam więc ogromną ilość .bson ze zrzutu MongoDB. Używam bsondump w wierszu polecenia, wyprowadzania danych wyjściowych jako stdin do Pythona. To z powodzeniem konwertuje z BSON na "JSON", ale w rzeczywistości jest ciągiem i pozornie nie legalnym JSON.Jak mogę użyć języka Python do przekształcenia bsonduktu MongoDB w JSON?

Na przykład linia przychodząca wygląda następująco:

{ "_id" : ObjectId("4d9b642b832a4c4fb2000000"), 
    "acted_at" : Date(1302014955933), 
    "created_at" : Date(1302014955933), 
    "updated_at" : Date(1302014955933), 
    "_platform_id" : 3, 
    "guid" : 72106535190265857 } 

Które I belive jest Mongo Extended JSON.

Kiedy czytam w takiej linii i zrobić:

json_line = json.dumps(line) 

uzyskać:

"{ \"_id\" : ObjectId(\"4d9b642b832a4c4fb2000000\"), 
\"acted_at\" : Date(1302014955933), 
\"created_at\" : Date(1302014955933), 
\"updated_at\" : Date(1302014955933), 
\"_platform_id\" : 3, 
\"guid\" : 72106535190265857 }\n" 

który jest nadal <type 'str'>.

Próbowałem również

json_line = json.dumps(line, default=json_util.default) 

(patrz pymongo json_util - wykrywanie spamu zapobiega trzeciego linku) który wydaje się tak samo jak wyjście wysypisk powyżej. obciążenia daje błąd:

json_line = json.loads(line, object_hook=json_util.object_hook) 
ValueError: No JSON object could be decoded 

Jak mogę przekształcić ciąg TenGen JSON w parsowany JSON? (celem końcowym jest przesyłanie danych oddzielonych tabulatorami do innej bazy danych)

+1

Czy spojrzał na 'bson'? http://pypi.python.org/pypi/bson/0.3.2 –

+0

Czy to coś innego niż usunięcie zależności Mongo? Nie rozumiem, jak to może być mój problem, ale popatrzę na to jeszcze trochę. –

+0

możliwy duplikat [Nie można deserializować obiektu PyMongo ObjectId z JSON] (http://stackoverflow.com/questions/8409194/unable-to-deserialize-pymongo-objectid-from-json) –

Odpowiedz

10

To, co masz, to zrzut w Mongo Extended JSON w trybie TenGen (patrz here). Niektóre z możliwych sposobów, aby przejść:

  1. Jeśli można zrzucić ponownie użyć trybu wyjściowego Strict przez API MongoDB REST. To powinno dać ci prawdziwy JSON zamiast tego, co masz teraz.

  2. Zastosowanie bson z http://pypi.python.org/pypi/bson/ przeczytać BSON masz już do struktur danych Pythona, a następnie zrobić cokolwiek trzeba na przetwarzanie tych (prawdopodobnie wyprowadzania JSON).

  3. Użyj powiązań Python w MongoDB, aby połączyć się z bazą danych, aby uzyskać dane w Pythonie, a następnie wykonaj dowolne przetwarzanie, którego potrzebujesz. (W razie potrzeby możesz skonfigurować lokalną instancję MongoDB i zaimportować do niej pliki zrzutu.)

  4. Konwersja Mongo Extended JSON z trybu TenGen na tryb ścisły. Możesz stworzyć oddzielny filtr do tego celu (odczytać ze standardowego wejścia, zamienić struktury TenGen na strukturach Strict i wyprowadzić wynik na standardowe wyjście) lub możesz to zrobić podczas przetwarzania danych wejściowych.

Oto przykład przy użyciu Python i wyrażeń regularnych:

import json, re 
from bson import json_util 

with open("data.tengenjson", "rb") as f: 
    # read the entire input; in a real application, 
    # you would want to read a chunk at a time 
    bsondata = f.read() 

    # convert the TenGen JSON to Strict JSON 
    # here, I just convert the ObjectId and Date structures, 
    # but it's easy to extend to cover all structures listed at 
    # http://www.mongodb.org/display/DOCS/Mongo+Extended+JSON 
    jsondata = re.sub(r'ObjectId\s*\(\s*\"(\S+)\"\s*\)', 
         r'{"$oid": "\1"}', 
         bsondata) 
    jsondata = re.sub(r'Date\s*\(\s*(\S+)\s*\)', 
         r'{"$date": \1}', 
         jsondata) 

    # now we can parse this as JSON, and use MongoDB's object_hook 
    # function to get rich Python data structures inside a dictionary 
    data = json.loads(jsondata, object_hook=json_util.object_hook) 

    # just print the output for demonstration, along with the type 
    print(data) 
    print(type(data)) 

    # serialise to JSON and print 
    print(json_util.dumps(data)) 

W zależności od celu, jeden z nich powinien być rozsądny punkt wyjścia.

+0

Tak, połączyłem się z tą rozszerzoną stroną JSON w moim pytaniu. Próbowałem biblioteki BSON i nie osiągnęło mojego celu. bsondump był jedyną rzeczą, którą mogłem dostać do pracy, ale daje mi ciąg. Zrzucanie lub ponowne ładowanie danych nie jest opłacalne. –

+1

@PeterNachbaur: Dodałem opcję do mojej odpowiedzi, aby pokazać, w jaki sposób można przekonwertować format TenGen JSON na Strict JSON. Czy to było coś więcej, o czym myślałeś? –

+0

Dzięki za dalszą pomoc :) teraz działa ładunek. Na koniec zakładam, że masz na myśli json.dumps, a nie json_util.dumps (ostatnie wydaje się nie istnieć), ale to nie działa. Jednak nie jestem pewien, czy potrzebuję tego teraz, gdy mam dyktando. Twoje zdrowie! –

6

Można konwertować linie pliku bson tak:

elementem
>>> import bson 
>>> bs = open('file.bson', 'rb').read() 
>>> for valid_dict in bson.decode_all(bs): 
.... 

Każdy valid_dict będzie ważny dict Pythona, który można przekonwertować do formatu JSON.

+0

To dla pętli nie działa :( Traceback (najnowsza rozmowę ostatni): Plik "", wiersz 1, w Plik „/usr/local/lib/python2.7/dist-packages/bson /__init__.py ", wiersz 473, w decode_all end = len (dane) - 1 TypeError: obiekt typu" file "nie ma len() –

8

ładowanie całego dokumentu z podpowiedzi do pamięci Pythona jest drogie.

Jeśli chcesz przesyłać strumieniowo zamiast ładować cały plik i wykonywać ładowanie wszystkie, możesz wypróbować tę bibliotekę.

https://github.com/bauman/python-bson-streaming

from bsonstream import KeyValueBSONInput 
from sys import argv 
for file in argv[1:]: 
    f = open(file, 'rb') 
    stream = KeyValueBSONInput(fh=f, fast_string_prematch="somthing") #remove fast string match if not needed 
    for id, dict_data in stream: 
     if id: 
     ...process dict_data... 
Powiązane problemy