使用Ruby在CouchDb中进行批量update_or_create优化

时间:2012-03-30 07:19:39

标签: ruby heroku nosql couchdb cloudant

我有以下方法来存储或更新事件json对象列表。我找不到couchdb的批量create_or_update函数,我不得不查询每个对象,看它是否存在于数据库中并相应地创建/更新。不幸的是,这是非常低效的,需要6分钟才能处理1725个事件。有人可以提出更好的设计吗?它必须在几秒钟内完成。我的couchdb实际上是一个ssl cloudant数据库,我的应用程序托管在Heroku上,它与heroku上的应用程序不同,实际上与cloudant结合使用。

def self.store(bulk, resource) 
            JSON::Validator.validate!(SCHEMA, bulk, :list => true)
            bulk.each{ |event|
                response = resource.get("/database-dev/_design/Event/_view/byEID?key=\"#{event['eid']}\"")
                if (response["rows"].nil? || response["rows"].empty?) then
                    o =  [('a'..'z'),('A'..'Z'),(0..9)].map{|i| i.to_a}.flatten  
                    o.push('-','_')
                    event['_id']  =  (0..50).map{ o[rand(o.length)]  }.join
                    event['resource'] = 'Event'
                    resource.post('/database-dev', event.to_json)
                else
                    resource.put("/database-dev/#{response['rows'][0]['id']}", event.to_json)   
                end
            }
        end 

1 个答案:

答案 0 :(得分:1)

您可以使用CouchDB bulk document API创建或更新。当然,由于您使用_rev值“盲目”,所以权衡是您可能会创建修订冲突。这对您来说可能不是问题,或者在某些情况下可能不可能或非常罕见(取决于您的应用)。只需在POST正文中添加"all_or_nothing":true选项即可。

或者,您可以在两次往返中进行批量创建或更新。首先获取所有文档修订,然后发布传统的_bulk_docs请求,并设置所有_rev值。

POST /database-dev/_all_docs
Content-Type: application/json

{"keys": ["id_1", "id_2", "bad_id"]}

HTTP/1.1 200 OK
...couch headers...

{"total_rows":10,"offset":0,"rows":[
  {"id":"id_1","key":"id_1","value":{"rev":"1-6919deb28bdb1d4cf5b53188be5683be"}},
  {"id":"id_2","key":"id_2","value":{"rev":"1-37bb8117bc6c7b182ca26aae16717408"}},
  {"key":"bad_id", "error":"not_found"}
]}

(您可以在请求视图时执行相同的操作。)

现在您知道要在_bulk_docs中发送的_rev的所有值。 (如果它具有"rev"值,请使用该值,否则,请将_rev保留为创建新文档。)