我使用的是couchdbkit(python 2.7),一次需要批量保存大约100个新项目。我想同时将有效负载(=附件)和元数据(=文档)保存在一起。
现在,我一个接一个地非常低效地保存这些项目,因为couchdbkit只允许在数据库中已经存在文档后使用put_attachment()
。这迫使我执行得非常缓慢。当我想保存一个项目时,我需要按照固定的顺序进行两次通信:首先是save()
项目,其次是put_attachment()
。
我想要的是用_attachments
在本地创建所有文档,并一次发送所有内容。以下代码不起作用,因为bulk_save
不处理附件[编辑:不正确,请参阅我的答案]
def setInBulk(self, key2value):
datetimeprop = DateTimeProperty()
def createItemToSave(thekey, thevalue):
pickled = cPickle.dumps(obj = value, protocol = 2).decode('latin1')
item = {"_id": key, "content": {"seeattachment": True, "ispickled" : True}, "creationtm": datetimeprop.to_json(datetime.datetime.utcnow()), "lastaccesstm": datetimeprop.to_json(datetime.datetime.utcnow())}
item ["_attachments"] = {
"theattachment":
{
"content_type":"application/octet-stream",
"data": pickled.encode('utf-8')
}
}
return item
docs = []
for key, value in key2value.iteritems():
docs.append(createItemToSave(key, value))
#this is what I want but it seems not to work
self.db.bulk_save(docs, all_or_nothing = True)
如何规避couchdbkit强加给我的一次写入限制?
我成功了!事实证明bulk_save
确实正确地处理了_attachments
字段。我做错的是数据编码。这是我的新代码:
def setInBulk(self, key2value):
datetimeprop = DateTimeProperty()
boolprop = BooleanProperty() #added
def createItemToSave(thekey, thevalue):
pickled = cPickle.dumps(obj = value, protocol = 2).decode('latin1')
#modified: usage of BooleanProperty for booleans
item = {"_id": key, "content": {"seeattachment": boolprop.to_json(True), "ispickled" : boolprop.to_json(True)}, "creationtm": datetimeprop.to_json(datetime.datetime.utcnow()), "lastaccesstm": datetimeprop.to_json(datetime.datetime.utcnow())} #modified
item ["_attachments"] = {
"theattachment":
{
"content_type":"application/octet-stream",
#modified: base64 encoding needed
"data": base64.encodestring(pickled.encode('utf-8'))
}
}
return item
docs = []
for key, value in key2value.iteritems():
docs.append(createItemToSave(key, value))
self.db.bulk_save(docs, all_or_nothing = True)
首先,我还添加了BooleanProperty的用法,只是为了确保所有内容都与JSON兼容。
其次,我未能对数据进行base64编码。需要纯的、未经过滤的base64代码。
不要尝试筛选base64代码。我被couchdb文档弄糊涂了,文档中写道:"请注意,您发送的任何base64数据都必须在一行字符上,所以对您的数据进行预处理,以删除任何回车和换行。"JSON-base64规范建议进行类似的过滤。这本身可能是真的,但bulk_save()
似乎已经注意到了这一点,做两次只会导致"不匹配"错误。