couchdb更新设计文档

时间:2016-07-14 22:16:34

标签: database deployment couchdb seeding couchdb-nano

我有一个nodejs应用程序,我使用nano使用以下脚本连接到我的couchdb:

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')
}

此脚本在每个服务器启动时运行,因此每次服务器(重新)启动时它都会尝试创建数据库'foo',如果数据库已经存在则只是静默失败。

我非常喜欢这个想法,因为这样我实际上是在应用程序级别维护数据库,而不是在我决定添加新数据库时手动创建数据库。

进一步采用这种方法,我还试图从应用程序级别维护我的设计文档。

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

显然,如果设计文档不存在,它只会插入设计文档。但是如果我更新了我的设计文档并希望更新它呢?

我试过了:

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

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

现在的问题是,每次服务器重新启动时,设计文档都会更新(例如,每次重新启动时都会获得一个新的_rev)。

现在......我的问题:)

1:这对于使用数据库和设计引导我的CouchDB是一种糟糕的方法吗?我应该考虑将部分迁移步骤作为部署过程的一部分吗?

2:我的设计文档是否有许多 _revs,基本上每次部署和服务器重启都是一个问题吗?即使文件本身没有改变?如果是这样,有没有办法只更新文件? (我想在我的应用程序中手动将_rev设置为某个值但不确定这是个好主意。)

3 个答案:

答案 0 :(得分:2)

  1. 你的方法似乎很合理。如果检查仅在重新启动时发生,则这甚至不会成为性能问题。
  2. 太多_rev s 可能会成为问题。 _revs的历史记录保存为_revs_info,并与文档本身(see the CouchDB docs for details)一起存储。根据您的设置,创建不必要的修订可能是一个错误的决定。
  3. 我们遇到了一些需要某些视图的服务器端脚本的类似挑战。我们的解决方案是计算旧设计文档和新设计文档的哈希值并进行比较。您可以对此作业使用任何散列函数,例如sha1md5。 只需记住在散列之前从旧文档中删除_rev,否则每次都会得到不同的哈希值。

答案 1 :(得分:1)

我尝试了像@Bernhard Gschwantner建议的md5比较。但是我遇到了一些困难因为我的情况我想在我的代码中用纯javascript在设计文档中编写map / reduce函数。

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

从CouchDb获取设计文档时返回转换为字符串的map / reduce函数:

  ...
  "by_name": {
    "map": "function (doc) {\n        emit(doc.name, null);\n      }"
  },
  ...

显然md5比较在这里确实不起作用。

通过在设计文档中添加版本号,我得到了非常简单的解决方案:

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

当我更新设计文档时,我只是增加版本号并将其与数据库中的版本号进行比较:

const fooDesign = {...}
foo.get('_design/foo', (err, design) => {
  if(err)
    return foo.insert(fooDesign);

  console.log('comparing foo design version', design.version, fooDesign.version);
  if(design.version !== fooDisign.version) {
    fooDesign._rev = design._rev;
    foo.insert(fooDesign, (err) => {
      if(err)
        return console.log('error updating foo design', err);
      console.log('foo design updated to version', fooDesign.version)
    });
  }
});

答案 2 :(得分:0)

再次重新审视您的问题:在最近的一个项目中,我使用了约翰内斯施密特的伟大couchdb-push模块。您可以免费获得有条件的更新,以及从其依赖项couchdb-compile继承的many other benefits

这个图书馆对我来说是一个隐藏的宝石。强烈推荐!