2012-03-30 13 views
1

Ich habe die folgende Methode, die eine Liste von Ereignis JSON-Objekten speichert oder aktualisiert. Ich konnte für couchdb keine Bulk-Funktion create_or_update finden, ich musste jedes Objekt abfragen und sehen, ob es in der Datenbank existiert und dementsprechend erstellt/aktualisiert wird. Leider ist dies sehr ineffizient, es dauert 6 Minuten für 1725 Ereignisse verarbeitet werden. Kann jemand ein besseres Design vorschlagen? Es muss in ein paar Sekunden getan werden. Meine Couchdb ist eigentlich eine ssl Cloud-Datenbank, und meine App ist auf Heroku gehostet, die anders ist als die App auf Heroku, die tatsächlich mit Cloudant kombiniert wird.Bulk update_or_create Optimierung in CouchDb mit Ruby

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 

Antwort

1

können Sie die CouchDB bulk document API verwenden, um-oder-Update zu erstellen. Da Sie mit den Werten _rev "blind fliegen", besteht der Nachteil darin, dass Sie möglicherweise Revisionskonflikte erzeugen. Das ist möglicherweise kein Problem für Sie, oder in manchen Fällen ist es unmöglich oder extrem selten (abhängig von Ihrer Anwendung). Fügen Sie einfach die "all_or_nothing":true Option in Ihrem POST-Körper hinzu.

Alternativ können Sie eine Massenerstellung oder -aktualisierung in zwei Round-Trips durchführen. Rufen Sie zuerst alle Dokumentversionen ab und senden Sie dann eine traditionelle _bulk_docs Anfrage mit allen _rev Werten.

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"} 
]} 

(Sie können das gleiche tun, wenn eine Ansicht anfordert.)

Jetzt wissen Sie alle Werte für _rev in den _bulk_docs zu senden. (Wenn es einen "rev" Wert hatte, verwenden Sie das, andernfalls lassen Sie _rev heraus, um ein neues Dokument zu erstellen.)