2014-02-27 66 views
3

我正在Python中使用MongoDB嘗試保存一個浮點數組。Pymongo BSON二進制保存和檢索?

我可以創建並正確地存儲*

我無法檢索數據可用格式。

>>> import random, array, pymongo 
>>> from bson.binary import Binary as BsonBinary 
>>> con = pymongo.Connection('localhost', 27017) 
>>> mm = con['testDatabase'] 
>>> vals = [random.random() *100 for x in range(1, 5)] 
>>> vals 
[2.9962593, 64.5582810776, 32.3781311717, 82.0606953423] 
>>> varray = array.array('f', vals) 
>>> varray 
array('f', [2.9962593, 64.5582810776, 32.3781311717, 82.0606953423]) 
>>> vstring = varray.tostring() 
>>> vstring 
'\xb7\[email protected]\xd7\x1d\x81B5\x83\x01B\x13\x1f\xa4B' 
>>> vbson = BsonBinary(vstring, 5) 
>>> vbson 
Binary('\xb7\[email protected]\xd7\x1d\x81B5\x83\x01B\x13\x1f\xa4B', 5) 
>>> doc1 = { 'something': 1 , 'else' : vbson} 
>>> doc1 
{'something': 1, 'else': Binary('\xb7\[email protected]\xd7\x1d\x81B5\x83\x01B\x13\x1f\xa4B', 5)} 
>>> mm.test1.insert(doc1) 
ObjectID('530f7af1d809d80d3db1f635') 
>>> gotdoc = mm.test1.find_one() 
>>> gotdoc 
{u'_id': ObjectId('530f7af1d809d80d3db1f635'), u'something': 3, u'else': Binary('\xb7\[email protected]\xd7\x1d\x81B5\x83\x01B\x13\x1f\xa4B', 5)} 
>>> gotfield = gotdoc['else'] 
>>> gotfield 
Binary('\xb7\[email protected]\xd7\x1d\x81B5\x83\x01B\x13\x1f\xa4B', 5) 
>>> from bson import BSON 
>>> BSON.decode(gotfield) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unbound method decode() must be called with BSON instance as first argument (got Binary instance instead) 
>>> gotfield.decode() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xb7 in position 0: ordinal not in range(128) 
>>> 

一旦我得到我的Python字符串回來,我可以讓我隨意浮標陣列回來。但是如何?

回答

3

讓我們通過錯誤:

  1. 的第一個錯誤出現,只是因爲你需要一個實際的BSON對象。請注意,您從未編碼過任何數據 - 創建對象並不意味着調用BSON.encode()

  2. 這就是PyMongo欺騙你一點。 bson.binary.Binary是運行時修補的strbytes實例(see source)。這就是爲什麼你會得到第二個錯誤:你所說的實際上是str.decode(),而不是BSON.decode()。因此,gotfield包含您最初存儲的隨機浮點數據,但對象本身有一些不同的方法(例如repr())綁定到它。

0

你需要在存放前,給數組編碼,而不應使用與Array.toString。請查看文檔here

from bson import BSON 
bson_string = BSON.encode({"hello": "world"}) 
>>> bson_string 
'\x16\x00\x00\x00\x02hello\x00\x06\x00\x00\x00world\x00\x00' 
>>> bson_string.decode() 
{u'hello': u'world'} 
+0

我不需要數據結構的bson編碼。我有一個有效的編碼和存儲的二進制對象。我需要將它轉換回我輸入的相同的東西。顯然,BSON.encode/decode不是正確的方法。 –

1

使用array.fromstring作爲最終解碼階段。我能到你在像這樣的相同點:

>>> from bson import Binary 
>>> import array 
>>> gotstring = Binary('\xb7\[email protected]\xd7\x1d\x81B5\x83\x01B\x13\x1f\xa4B', 5) 

最後:

>>> a = array.array('f') 
>>> a.fromstring(gotstring) 
>>> a 
array('f', [2.9962594509124756, 64.55828094482422, 32.37813186645508, 82.0606918334961]) 
0

BSON.decode(gotfield)

它有一個類型錯誤的問題,你應該把它寫像下面

BSON.decode(bson.BSON(gotfield))

2

我來了〜我只是想辦法。希望這可以幫助你以某種方式。

from cStringIO import StringIO 
from PIL import Image 

保存圖像:

content = StringIO(f.read()) 

c = dict(
    content=bson.binary.Binary(content.getvalue()), 
) 
# insert dict into my database, sha1 is primary key 
image_data[sha1] = c 

檢索圖像:

f = image_data[sha1] 
image = Image.open(StringIO(f['content'])) 

---- ----編輯

如果你想返回從Web服務器的圖像。像這樣:

f = image_data[sha1] 
# f['mime'] is the type of image, for example 'png'. 
resp = Response(f['content'], mimetype='image/' + f['mime']) 
return resp