문제

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..?

도움이 되었습니까?

해결책

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.

다른 팁

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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top