Differences between revisions 27 and 28
Revision 27 as of 2013-06-05 21:26:25
Size: 6642
Comment: real doc link
Revision 28 as of 2014-04-23 12:18:05
Size: 6643
Editor: BeckyConning
Comment:
Deletions are marked like this. Additions are marked like this.
Line 105: Line 105:
{{{#!highlight javacript {{{#!highlight javascript

The official documentation has moved to http://docs.couchdb.org — The transition is not 100% complete, but http://docs.couchdb.org should be seen as having the latest info. In some cases, the wiki still has some more or older info on certain topics inside CouchDB.

You need to be added to the ContributorsGroup to edit the wiki. But don't worry! Just email any Mailing List or grab us on IRC and let us know your user name.

Document Update Handlers

See also the official documentation for this topic.

Basics

Update handlers are functions that clients can request to invoke server-side logic that will create or update a document. This feature allows a range of use cases such as providing a server-side last modified timestamp, updating individual fields in a document without first getting the latest revision, etc.

When the request to an update handler includes a document ID in the URL, the server will provide the function with the most recent version of that document. You can provide any other values needed by the update handler function via the POST/PUT entity body or query string parameters of the request.

This feature was first implemented in CouchDB version 0.10.

Creating an Update Handler

You can specify any number of update handler functions in a design document, under the "updates" attribute.

For example:

   1 {
   2   updates: {
   3 
   4     "hello" : "function(doc, req) {
   5       if (!doc) {
   6         if (req.id) {
   7           return [{
   8             _id : req.id
   9           }, 'New World']
  10         }
  11         return [null, 'Empty World'];
  12       }
  13       doc.world = 'hello';
  14       doc.edited_by = req.userCtx;
  15       return [doc, 'hello doc'];
  16     }",
  17 
  18     "in-place" : "function(doc, req) {
  19       var field = req.form.field;
  20       var value = req.form.value;
  21       var message = 'set '+field+' to '+value;
  22       doc[field] = value;
  23       return [doc, message];
  24     }",
  25 
  26     "in-place-query" : "function(doc, req) {
  27       var field = req.query.field;
  28       var value = req.query.value;
  29       var message = 'set '+field+' to '+value;
  30       doc[field] = value;
  31       return [doc, message];
  32     }",
  33 
  34     "bump-counter" : "function(doc, req) {
  35       if (!doc.counter) doc.counter = 0;
  36       doc.counter += 1;
  37       var message = '<h1>bumped it!</h1>';
  38       return [doc, message];
  39     }",
  40 
  41     "error" : "function(doc, req) {
  42       superFail.badCrash;
  43     }",
  44 
  45     "xml" : "function(doc, req) {
  46       var xml = new XML('<xml></xml>');
  47       xml.title = doc.title;
  48       var posted_xml = new XML(req.body);
  49       doc.via_xml = posted_xml.foo.toString();
  50       var resp =  {
  51         'headers' : {
  52           'Content-Type' : 'application/xml'
  53         },
  54         'body' : xml
  55       };
  56 
  57        return [doc, resp];
  58      }"
  59   }
  60 }

The handler function takes the most recent version of the document from the database and the http request environment as parameters. It returns a two-element array: the first element is the (updated or new) document, which is committed to the database. If the first element is null no document will be committed to the database. If you are updating an existing, it should already have an _id set, and if you are creating a new document, make sure to set its _id to something, either generated based on the input or the req.uuid provided. The second element is the response that will be sent back to the caller.

If you want the client to get the changed document (without an additional request) you can return it as the second element of the return array, but you need to turn it into a string first.

   1 {
   2   updates: {
   3     "in-place": "function (doc, req) {
   4       doc.field = req.form.field.new_value;
   5 
   6       return [doc, toJSON(doc)];
   7     }"
   8   }
   9 }

Note The document returned in this manner will have the "old" _rev, see the response section for how retrieve the new/current _rev.

Request

The request parameter will look something like this for a update function designed to create a new document:

   1 {
   2   "info": {
   3     "db_name": "loot",
   4     /* and many more */
   5     "committed_update_seq": 27
   6   },
   7   "id": null,
   8   "uuid": "7f8a0e3833bcc7161cfab80275221dc1",
   9   "method": "POST",
  10   "path": ["loot", "_design", "haul", "_update", "new"],
  11   "query": {},
  12   "headers": {"Accept": "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5" /* and many more */},
  13   "body": "name=Jeff",
  14   "peer": "127.0.0.1",
  15   "form": {"name": "Jeff"},
  16   "cookie": {},
  17   "userCtx": {"db": "loot", "name": null, "roles": []}
  18 }

Since no ID was passed, the request doesn't have an ID. However, the CouchDB server helpfully provides a UUID so you can create a new document with a unique ID and be sure it won't conflict with any document in the database already.

The server also parses the POST body into a Javascript object called form and does the same with the query string, in query.

Response

If the first member of the return array is a document the HTTP response headers include a "X-Couch-Update-NewRev" with the _rev number from the document after the change/create has been applied. This can be used to keep the client's object in sync with that in the database.

The second member of the return array is the HTTP response. This can be a javascript object with headers and a body:

   1 var resp =  {
   2   "headers" : {
   3     "Content-Type" : "application/xml"
   4   },
   5   "body" : doc.xml
   6 };

or just a plain string:

    <p>Update function complete!</p>

In addition to setting headers, you may set a code attribute on the object in order to control the HTTP status.

Usage

To invoke a handler, use one of:

  • a PUT request against the handler function with a document id: /<database>/_design/<design>/_update/<function>/<docid>

  • a POST request agasint the handler function without a document id: /<database>/_design/<design>/_update/<function>

The document id specified in a PUT request URI is available in the update handler as id property on the request object (req.id).

For example, to invoke the in-place-query handler defined above, PUT to:

http://127.0.0.1:5984/<my_database>/_design/<my_designdoc>/_update/in-place-query/<mydocId>?field=title&value=test

This means that unlike document validators, the user's intent must be clear by calling this individual handler explicitly. In this sense, you should think about an _update handler as complementary to _show functions, not to validate_doc_update functions.

For more information, look at update_documents.js in the test suite.

Document_Update_Handlers (last edited 2014-04-23 12:18:05 by BeckyConning)