Atomic Upsert operations in couchdb

In persistence vocabulary, Upsert stands for (Update if existing else insert). Lets take an entity Patient. When the upsert operation is invoked with a new (not yet persisted) Patient, a new entry is made in the database, while when updating an existing Patient, the old entry in the database is updated with the current value.

Upsert is supported out of the box in databases like mysql. When a database supports, Upsert out of the box, it means that the entire operation can be executed in a single transaction. This post explains how Upsert can be achieved using a single transaction (HTTP PUT/POST) in couchdb.

The simplest way to perform an Upsert in couchdb is to have something like the following pseudo code in the application layer.

Query latest revision of document

If document == null
    save entity
else
    update entity


Obviously, this requires you to fetch the latest revision of document from couchdb in one request and save/update in another request. One small problem. Since couchdb does not provide any locks, we cannot ensure that the document that we have in hand at the application layer is of the latest revision. Hence, upsert should be made atomic.

Enter couchdb update handlers. With the following update handler, upsert can be achieved using a single request.

function(doc, req){ 
    log(req);
     if(!doc){
        if(req.id){
            return [JSON.parse(req.body), {}];
        }else{
            return [null, {}];
        }
    }else{
        var updatedDoc = JSON.parse(req.body);
        //update logic here
        return [doc, {}];
    }
}

In the above function, req stands for the http request. You can either pass id as a parameter of the request, if not couchdb will generate a uuid. What this means is that, you have to know the ID of the document when the document is already present in the database and you wish to update it with new data. Hence for this scheme to work, you must come up with a function which will generate an id given an entity ( similar to an artificial key).

Please note that couchdb update handler is append only. Which means that the document returned from the update handler will be assigned a new revision.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s