2016-07-14 83 views
1

我在那裏我使用nano與下面的腳本連接到我的CouchDB的一個的NodeJS應用: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') 
} 

這個腳本是在每個服務器開始運行,所以它試圖創建數據庫「富'每次服務器(重新啓動),只是在數據庫已經存在的情況下靜靜地失敗。

我非常喜歡這個想法,因爲這樣我實際上在應用程序級維護數據庫,並且在我決定添加新數據庫時不需要手動創建數據庫。

採取這種方法更進一步我也試圖從應用程序級別維護我的設計文檔。

... 
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每次重啓時)。

現在...我的問題(S):)

1:這是提供引導我的CouchDB與數據庫和設計一個不錯的辦法?作爲我的部署過程的一部分,我應該考慮一些遷移步驟嗎?

2:這是一個問題,我的設計文檔得到許多 _revs,基本上爲每個部署和服務器重新啓動?即使文件本身沒有改變?如果是這樣,是否有辦法只更新文件,如果它改變了? (我想在我的應用程序中手動設置_rev值,但很不確定這是一個好主意)。

回答

2
  1. 你的方法似乎很合理。如果檢查僅在重新啓動時發生,這甚至不會成爲性能問題。
  2. 太多_rev s 可能會變成的一個問題。 _revs的歷史記錄保存爲_revs_info並與文檔本身(see the CouchDB docs for details)一起存儲。根據您的設置,創建不必要的修訂可能是一個錯誤的決定。

對於某些需要特定視圖的服務器端腳本,我們有類似的挑戰。我們的解決方案是計算舊的和新的設計文檔的散列值並進行比較。您可以對此作業使用任何散列函數,例如sha1md5。 只記得在散列之前從舊文檔中刪除_rev,否則每次都會得到不同的散列值。

+0

謝謝Bernhard。你的解釋真的很有幫助。我只是通過比較設計文檔來接受你的建議,但遇到了一些麻煩,將它們與md5進行比較......我根據你的建議在下面發佈了我自己的解決方案。你可否提供你的意見? –

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) 
    }); 
    } 
}); 
+0

這也很好,更簡單。但是,如果你想使用md5散列,你可以通過遍歷對象屬性並調用'prop.toString()'將函數轉換爲字符串,從而將javascript函數轉換爲字符串。但是,這是更多的工作,所以版本領域是更簡單和更容易理解的解決方案。 –

0

再次重溫你的問題:在最近的一個項目中,我使用的偉大couchdb-push模塊約翰內斯·施密特。您可以免費獲得有條件更新,manyotherbenefits繼承自其依賴關係couchdb-compile

這個庫竟然是我隱藏的寶石。強烈推薦!