couchdb更新设计文档
couchdb update design doc
我有一个 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:我的设计文档得到 many _revs,基本上是每次部署和服务器重新启动,这是一个问题吗?即使文件本身没有改变?如果是这样,有没有办法只在文件发生变化时更新文件? (我想在我的应用程序中手动将 _rev 设置为某个值,但非常不确定这是否是个好主意)。
- 你的做法似乎很合理。如果检查仅在重新启动时发生,这甚至不会成为性能问题。
- 太多
_rev
可能会成为一个问题。 _revs 的历史记录保存为 _revs_info
并与文档本身一起存储 (see the CouchDB docs for details)。根据您的设置,创建不必要的修订可能是一个错误的决定。
我们遇到了一些需要特定视图的服务器端脚本的类似挑战。我们的解决方案是计算新旧设计文档的哈希值并进行比较。您可以为此作业使用任何哈希函数,例如 sha1 or md5。
请记住在散列之前从旧文档中删除 _rev,否则每次都会得到不同的散列值。
我尝试了@Bernhard Gschwantner 建议的 md5 比较。但是我 运行 遇到了一些困难,因为在我的情况下,我想在我的代码中以纯 javascript 编写设计文档中的 map/reduce 函数。
const design = {
_id: "_design/foo",
views: {
by_name: {
map: function(doc) {
emit(doc.name, null);
}
}
}
}
从 CouchDb 获取设计文档时 returns 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)
});
}
});
再次重温您的问题:在最近的一个项目中,我使用了从其依赖项 couchdb-compile
.
继承的伟大 couchdb-push module by Johannes Schmidt. You get conditional updates for free, alongside with many other benefits
那个图书馆对我来说原来是一个隐藏的gem。强烈推荐!
我有一个 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:我的设计文档得到 many _revs,基本上是每次部署和服务器重新启动,这是一个问题吗?即使文件本身没有改变?如果是这样,有没有办法只在文件发生变化时更新文件? (我想在我的应用程序中手动将 _rev 设置为某个值,但非常不确定这是否是个好主意)。
- 你的做法似乎很合理。如果检查仅在重新启动时发生,这甚至不会成为性能问题。
- 太多
_rev
可能会成为一个问题。 _revs 的历史记录保存为_revs_info
并与文档本身一起存储 (see the CouchDB docs for details)。根据您的设置,创建不必要的修订可能是一个错误的决定。
我们遇到了一些需要特定视图的服务器端脚本的类似挑战。我们的解决方案是计算新旧设计文档的哈希值并进行比较。您可以为此作业使用任何哈希函数,例如 sha1 or md5。 请记住在散列之前从旧文档中删除 _rev,否则每次都会得到不同的散列值。
我尝试了@Bernhard Gschwantner 建议的 md5 比较。但是我 运行 遇到了一些困难,因为在我的情况下,我想在我的代码中以纯 javascript 编写设计文档中的 map/reduce 函数。
const design = {
_id: "_design/foo",
views: {
by_name: {
map: function(doc) {
emit(doc.name, null);
}
}
}
}
从 CouchDb 获取设计文档时 returns 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)
});
}
});
再次重温您的问题:在最近的一个项目中,我使用了从其依赖项 couchdb-compile
.
那个图书馆对我来说原来是一个隐藏的gem。强烈推荐!