2011-01-12 67 views
2

在我看來,我想創建一個新對象來返回,而不是傳遞給我的地圖函數的對象。我想做一些驗證,並添加一些字段到新的對象。我的觀點地圖功能看起來像這樣(有不減少):CouchDB:將字段添加到視圖中的「doc」

function(doc) { 
    if(doc.type == "mytype") { 
     var newobj = null; 
     if(doc.someObjField) { 
      newobj = doc.someObjField; //LINE 5: want a copy but get a reference 
     } 
     else { 
      newobj = new Object();  //field didn't exist create a new object 
     } 

     newobj.superId = doc._id;  //these fields get added to the DB 
     newobj.superName = doc.name; 
     newobj.newField = doc.field; 

     emit(doc._id, newobj); 
    } 
} 

的問題是,當這種觀點的運行,它最終增加了一些新的領域在數據庫中的文檔。在蒲團中編輯文檔時我看不到字段,但是它們在文檔的每個視圖中都顯示出來。

我認爲這是因爲LINE 5創建了文檔的該字段而不是副本的引用。這是否意味着我必須在所有視圖中包含clone()函數才能獲得我想要的內容?也許我在想這個錯誤?

更新:我使用CouchDB版本1.0.0並升級到版本1.0.1,似乎行爲已經改變。在之前的版本中,當「doc」在一個視圖中被修改時,修改出現在所有視圖中。在最新版本中,似乎並非如此。

+0

你的描述有點不清楚。你是否試圖使用視圖來修改數據庫?視圖是隻讀數據轉換。當您使用蒲團並單擊視圖行時,它會將您帶到用於生成該行的文檔。您在視圖中「創建」的文檔在數據庫中不存在,它就是您發出的()'d。 – 2011-01-18 16:03:52

+0

我想修改視圖返回的結果,而不是保存在數據庫中的文檔。我遇到的問題是數據庫中的文檔似乎被修改並與其他視圖混淆。 – 2011-01-19 16:07:23

回答

3

newobj = doc.someObjField確實是一個參考,而不是一個副本,所以你將不得不遍歷doc.someObjField的屬性,並將它們複製到一個新的對象。

這不是小事,下面顯示瞭如何讓一個淺克隆一個例子:

// get the class of an object, this is a lot better than messing with typeof and instanceof 
function is(type, obj) { 
    return Object.prototype.toString.call(obj).slice(8, -1) === type; 
} 

function copy(val) { 
    if (is('Object', val)) { // shallow clone objects 
     var obj = {}; 
     for (var f in val) { 
      if (val.hasOwnProperty(f)) { 
       obj[f] = val[f]; 
      } 
     } 
     return obj; 

    } else { 
     return is('Array', val) ? val.slice() : val; // shallow clone arrays 
    } 
} 

您的代碼應該是這樣的:

newobj = doc.someObjField ? copy(doc.someObjField) : {}; 

現在,如果你someObjField有對象或數組作爲它們的屬性,那些將只是引用,所以你必須遞歸地克隆它們。