2

我正在使用 couchdbkit (python 2.7),我需要一次批量保存大约 100 个新项目。我想同时保存有效负载(=附件)和元数据(=doc)。

现在我一个一个地保存这些项目的效率非常低,因为 couchdbkit 只允许put_attachment()在数据库中已经存在一个文档之后。这迫使我执行非常缓慢。当我想保存 1 个项目时,我需要按固定顺序进行两次沟通:首先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 强加给我的一次只写一个限制?

4

1 回答 1

1

我让它工作了!事实证明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()似乎已经解决了这个问题,并且这样做两次只会导致“badmatch”错误。

于 2015-04-04T06:44:18.553 回答