2012-08-08 24 views
16

Vì vậy, tôi có một số lượng rất lớn .bson từ một bãi chứa MongoDB. Tôi đang sử dụng bsondump trên dòng lệnh, đường ống đầu ra như stdin để python. Điều này chuyển đổi thành công từ BSON thành 'JSON' nhưng thực tế nó là một chuỗi và dường như không phải là JSON hợp pháp.Làm thế nào tôi có thể sử dụng Python để chuyển bsondump của MongoDB thành JSON?

Ví dụ một dòng đến trông như thế này:

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

Mà I belive là Mongo Extended JSON.

Khi tôi đọc trong một dòng như vậy và làm:

json_line = json.dumps(line) 

tôi nhận được:

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

nào vẫn là <type 'str'>.

Tôi cũng đã cố gắng

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

(thấy pymongo json_util - phát hiện spam ngăn chặn một liên kết ba) Mà dường như để sản xuất các giống như bãi trên. tải cho một lỗi:

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

Vì vậy, làm cách nào tôi có thể chuyển chuỗi JSON của TenGen thành JSON phân tích cú pháp? (mục tiêu cuối cùng là truyền dữ liệu được phân tách bằng tab sang cơ sở dữ liệu khác)

+1

Các bạn đã nhìn 'bson'? http://pypi.python.org/pypi/bson/0.3.2 –

+0

Điều đó có làm được gì khác ngoài việc loại bỏ sự phụ thuộc Mongo không? Tôi không hiểu làm thế nào mà có thể là vấn đề của tôi, nhưng tôi sẽ xem xét nó một số chi tiết. –

+0

có thể trùng lặp của [Không thể deserialize PyMongo ObjectId từ JSON] (http://stackoverflow.com/questions/8409194/unable-to-deserialize-pymongo-objectid-from-json) –

Trả lời

10

Những gì bạn có là kết xuất trong Mongo Extended JSON ở chế độ TenGen (xem here). Một số cách có thể để đi:

  1. Nếu bạn có thể đổ lại, hãy sử dụng chế độ đầu ra nghiêm ngặt thông qua API REST MongoDB. Điều đó sẽ cung cấp cho bạn JSON thực thay vì những gì bạn có bây giờ.

  2. Sử dụng bson từ http://pypi.python.org/pypi/bson/ để đọc BSON bạn đã có trong cấu trúc dữ liệu Python và sau đó thực hiện bất kỳ việc xử lý nào bạn cần trên (có thể xuất ra JSON).

  3. Sử dụng các liên kết Python MongoDB để kết nối với cơ sở dữ liệu để lấy dữ liệu vào Python và sau đó thực hiện bất kỳ thao tác nào bạn cần. (Nếu cần, bạn có thể thiết lập một cá thể MongoDB cục bộ và nhập các tệp đã bán của bạn vào đó.)

  4. Chuyển đổi Mongo mở rộng JSON từ chế độ từ TenGen sang chế độ nghiêm ngặt. Bạn có thể phát triển một bộ lọc riêng để thực hiện nó (đọc từ stdin, thay thế cấu trúc TenGen bằng cấu trúc Strict, và xuất kết quả trên stdout) hoặc bạn có thể làm điều đó khi bạn xử lý đầu vào.

Dưới đây là một ví dụ sử dụng Python và biểu thức thông thường:

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)) 

Tùy thuộc vào mục tiêu của bạn, một trong những phải là một điểm khởi đầu hợp lý.

+0

Có, tôi đã liên kết với trang JSON mở rộng đó trong câu hỏi của mình. Tôi đã thử thư viện BSON và nó không hoàn thành mục tiêu của tôi. bsondump là điều duy nhất tôi có thể làm việc, nhưng nó cho tôi một chuỗi. Dumping hoặc tải lại dữ liệu không phải là lựa chọn khả thi. –

+1

@PeterNachbaur: Tôi đã thêm tùy chọn vào câu trả lời của mình để cho biết cách bạn có thể chuyển đổi định dạng JSON TenGen thành JSON chuẩn. Đó có phải là những gì bạn có trong tâm trí? –

+0

Cảm ơn bạn đã tiếp tục trợ giúp :) ngay bây giờ tải đang hoạt động. Cuối cùng tôi giả sử bạn có nghĩa là json.dumps không json_util.dumps (sau này dường như không tồn tại) nhưng điều đó không hoạt động. Tuy nhiên, tôi không chắc tôi cần nó bây giờ mà tôi có một dict. Chúc mừng! –

6

Bạn có thể chuyển đổi dòng của tập tin bson như thế này:

yếu tố
>>> import bson 
>>> bs = open('file.bson', 'rb').read() 
>>> for valid_dict in bson.decode_all(bs): 
.... 

Mỗi valid_dict sẽ là một dict python hợp lệ mà bạn có thể chuyển đổi sang json.

+0

Đó vòng lặp for không hoạt động :( Traceback (gần đây nhất gọi cuối cùng): File "", dòng 1, trong File "/usr/local/lib/python2.7/dist-packages/bson /__init__.py ", dòng 473, trong decode_all end = len (dữ liệu) - 1 LoạiError: đối tượng của loại 'tệp' không có len() –

8

tải toàn bộ tài liệu bson vào bộ nhớ python là tốn kém.

Nếu bạn muốn truyền phát trực tuyến thay vì tải toàn bộ tệp và tải tất cả, bạn có thể thử thư viện này.

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... 
Các vấn đề liên quan