Domanda

I know there are a couple of similar questions out there (like this one for example: CouchDB - trigger code when creating or updating document) which refer to "update handlers" in CouchDB but I have not been able to see how they solve the issue;

  • Each time a new document is created in my CouchDB database I want to add a timestamp
  • I've created an update handler in _design/updatehandlers and verified that it gets called:

    "timestampadd" : "function(doc,req) {
    if (!doc) { 
        if ( req.id) { 
            return [{_id : req.id, timestamp : new Date().getTime()}];
        }
        return [null,'added empty'];
    }
    doc.timestamp = new Date().getTime(); 
    return [doc,'added at ' + doc.timestamp];
    }"
    

My question is this; How do can I use this function when creating a new document in the database, i.e. one which I would normally create by doing a POST to

    http://mycouchdb:5984/test_db

where I want couchdb to create an _id for me (see for example: http://docs.cloudant.com/tutorials/crud/index.html#create)?

If I follow the documentation to do it (in Python in this example) I would issue a Post like so;

   requests.post("http://mycouchdb:5984/test_db/_design/updatehandlers/_update/timestampadd",headers={'Content-type':'application/json'},data='{"foo":"bar"})

but here the update function timestampadd takes the "doc==null && req.id==null path, obviously, since the document has not yet been created and I didn't specify an ID. This leads me to believe that the update function can only be invoked on an existing document, despite what the documentation seems to imply, or am I wrong?

I can invoke the update on an existing document and add the timestamp without any trouble, that works well, but the issue here was to add a timestamp as the document is created.

Is that even possible..?

È stato utile?

Soluzione

Yes you can do that with an update handler. You're on the right track. Here are the 3 cases:

Create a doc without specifying an id

The path taken is !doc && !req.id. That's your example. Instead of returning null, you should build a new document and return it. You can use req.uuid to populate the _id. For instance:

return [{_id : req.uuid, timestamp : new Date().getTime()}, 'created new doc'];

Create a doc with a given id

The path taken is !doc && req.id. You got this one right.

Update an existing doc

The path taken is doc. You got this one right.

Altri suggerimenti

Thanks to Simon for pointing me in the right direction. This was the script I ended up using;

function(doc,req) { 
   if (!doc) { 
       var new_doc = {}; 
       if ( req.id) { 
           new_doc._id = req.id; 
       } else { 
            new_doc._id = req.uuid; 
       } 
       new_doc.timestamp = new Date().getTime(); 
       new_doc.body = eval('(' + req.body + ')'); 
       return [new_doc,'added new']; 
   } 
   doc.timestamp = new Date().getTime(); return [doc,'updated'];
 }

Notice that I had to add an "eval" with the body passed in through the request to add the contents of the new document to the ones provided by the caller.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top