Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CouchDB Document Update Handlers (in-place updates)

Tags:

couchdb

http://wiki.apache.org/couchdb/Document_Update_Handlers

CouchDB ( 0.10 and above ) supports in-place updates now. I'm having trouble understanding how it works. I tried to use the example provided but I couldn't get it to work.

Can someone provide some examples and uris used to access the in-place updates.

Thanks

like image 202
Jason Avatar asked Jun 04 '10 06:06

Jason


2 Answers

The example function in-place is not the same as "in-place" updates in other databases. CouchDB still uses an append-only architecture; document update handlers still create a new doc revision, etc.

Still, update handlers are quite convenient and worth learning.

Suppose you have a document with an accumulator. You want to accumulate an integer in a document with just one HTTP query, specifying the increment amount using an amount parameter. Consider the following commands:

curl -X PUT http://localhost:5984/db # Returns {"ok":true}  curl -H "Content-Type:application/json" -X POST http://localhost:5984/db/_bulk_docs -d @- {"docs":   [     {"_id": "my_doc", "number": 23},     {"_id": "_design/app",       "updates": {         "accumulate": "function (doc, req) {                          var inc_amount = parseInt(req.query.amount);                          doc.number = doc.number + inc_amount;                          return [doc, \"I incremented \" +                                       doc._id + \" by \" +                                       inc_amount];                        }"       }     }   ] } # Returns [{"id":"my_doc","rev":"1-8c9c19a45a7e2dac735005bbe301eb15"}, #          {"id":"_design/app","rev":"1-83ec85978d1ed32ee741ce767c83d06e"}] 

(Remember to press end-of-file, ^D, after the JSON object in the POST.)

Next confirm the document for accumulation (my_doc) exists:

curl http://localhost:5984/db/my_doc # Returns {"_id":"my_doc","_rev":"1-8c9c19a45a7e2dac735005bbe301eb15", #          "number":23} 

Now you can call the accumulate update handler with an amount parameter to update the field.

curl -X PUT \  http://localhost:5984/db/_design/app/_update/accumulate/my_doc?amount=15 # Returns: I incremented my_doc by 15  curl http://localhost:5984/db/my_doc # Returns {"_id":"my_doc","_rev":"2-<whatever>", #          "number":38} 

Notice that the new number value is 38, the value of 23 + 15.

like image 182
JasonSmith Avatar answered Sep 18 '22 15:09

JasonSmith


Here is something I found very useful when playing with the above example. Once you've installed an update handler, you can use it to update the update-handler itself. For instance, if your update handler is in update.json, you could do the following:

curl --dump-header - -H "Content-Type:application/json" -X POST http://localhost:5984/db/_design/app/_update/modifyinplace/_design/app -d @update.json

where update.json contains:

{"_id": "_design/app",
    "updates": {
        "modifyinplace": "function (doc, req) { var fields = JSON.parse(req.body); for (var i in fields) { doc[i] = fields[i] } var resp = eval(uneval(doc)); delete resp._revisions; return [doc, toJSON(resp)]; }"
     }
}

A few things are noteworthy. The statement var resp = eval(uneval(doc)) clones doc. There is more information on cloning here. Since the _revisions field can get large, deleting it in the response makes sense for my use case. The use of toJSON(resp) sends back the response as a string, however, the value of _rev in a successful response will be wrong. To get the correct revision of a successful update, look at X-Couch-Update-NewRev in the response header. The update could very well not succeed and result in a conflict, as addressed here

like image 36
Ram Rajamony Avatar answered Sep 17 '22 15:09

Ram Rajamony