couchdbkit:如何使用附件进行bulk_save



我使用的是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()似乎已经注意到了这一点,做两次只会导致"不匹配"错误。

最新更新