Pymongo BSON二进制保存和检索?

时间:2014-02-27 18:52:00

标签: python mongodb pymongo bson

我在Python中使用MongoDB尝试紧紧保存一系列浮点数。

我可以正确创建和存储*

我无法以可用的格式检索数据。

>>> 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\xc2?@\xd7\x1d\x81B5\x83\x01B\x13\x1f\xa4B'
>>> vbson = BsonBinary(vstring, 5)
>>> vbson
Binary('\xb7\xc2?@\xd7\x1d\x81B5\x83\x01B\x13\x1f\xa4B', 5)
>>> doc1 = { 'something': 1 , 'else' : vbson}
>>> doc1
{'something': 1, 'else': Binary('\xb7\xc2?@\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\xc2?@\xd7\x1d\x81B5\x83\x01B\x13\x1f\xa4B', 5)}
>>> gotfield = gotdoc['else']
>>> gotfield
Binary('\xb7\xc2?@\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字符串,我就可以得到我的随机浮点数组。但是如何?

5 个答案:

答案 0 :(得分:3)

让我们来看看错误:

  1. 出现第一个错误只是因为您需要一个实际的BSON对象。请注意,您从未编码任何数据 - 创建bson.binary.Binary对象并不意味着调用BSON.encode()

  2. 这就是PyMongo欺骗你的地方。 bson.binary.Binary是运行时修补的strbytes实例(see source)。这就是您收到第二个错误的原因:您调用的内容实际上是str.decode(),而不是BSON.decode()。因此,gotfield 包含您最初存储的随机浮点数据,但对象本身有一些不同的方法(例如repr())绑定到它。

答案 1 :(得分:3)

我来了〜我找到了一条路。希望这可能会以某种方式帮助你。

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

---- ---- EDIT

如果要从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

答案 2 :(得分:1)

使用array.fromstring进行最后的解码阶段。我可以到达你所在的同一地点:

>>> from bson import Binary
>>> import array
>>> gotstring = Binary('\xb7\xc2?@\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])

答案 3 :(得分: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'}

答案 4 :(得分:0)

  

BSON.decode(gotfield)

它有一个TypeError问题,你应该像下面那样写它

  

BSON.decode(bson.BSON(gotfield))