Search code examples
databasedeploymentcouchdbseedingcouchdb-nano

couchdb update design doc


I have a nodejs application where i connect to my couchdb using nano with the following script:

const { connectionString } = require('../config');

const nano = require('nano')(connectionString);

// creates database or fails silent if exists
nano.db.create('foo');

module.exports = {
  foo: nano.db.use('foo')
}

This script is running on every server start, so it tries to create the database 'foo' every time the server (re)starts and just fails silently if the database already exists.

I like this idea a lot because this way I'm actually maintaining the database at the application level and don't have to create databases manually when I decide to add a new database.

Taking this approach one step further I also tried to maintain my design docs from application level.

... 
nano.db.create('foo');

const foo = nano.db.use('foo');

const design = {
  _id: "_design/foo",
  views: {
    by_name: {
      map: function(doc) {
        emit(doc.name, null);
      }
    }
  }
}

foo.insert(design, (err) => {
  if(err)
    console.log('design insert failed');
})

module.exports = {
  foo
}

Obviously this will only insert the design doc if it doesn't exist. But what if I updated my design doc and want to update it?

I tried:

foo.get("_design/foo", (err, doc) => {
  if(err)
    return foo.insert(design);

  design._rev = doc._rev
  foo.insert(design);
})

The problem now is that the design document is updated every time the server restarts (e.g it gets a new _rev on every restart).

Now... my question(s) :)

1: Is this a bad approach for bootstrapping my CouchDB with databases and designs? Should I consider some migration steps as part of my deployment process?

2: Is it a problem that my design doc gets many _revs, basically for every deployment and server restart? Even if the document itself hasn't changed? And if so, is there a way to only update the document if it changed? (I thought of manually setting the _rev to some value in my application but very unsure that would be a good idea).


Solution

    1. Your approach seems quite reasonable. If the checks happen only at restarts, this won't even be a performance issue.
    2. Too many _revs can become a problem. The history of _revs is kept as _revs_info and stored with the document itself (see the CouchDB docs for details). Depending on your setup, it might be a bad decision to create unnecessary revisions.

    We had a similar challenge with some server-side scripts that required certain views. Our solution was to calculate a hash over the old and new design document and compare them. You can use any hashing function for this job, such as sha1 or md5. Just remember to remove the _rev from the old document before hashing it, or otherwise you will get different hash values every time.