CouchDB:在视图中向“doc”添加字段

时间:2011-01-12 19:23:52

标签: javascript couchdb

在我的视图中,我想创建一个要返回的新对象,而不是传递给我的map函数的对象。我想做一些验证并向新对象添加一些字段。我对视图的map函数看起来像这样(没有reduce):

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

问题是,当此视图运行时,它最终会向数据库中的文档添加一些新字段。在Futon中编辑文档时我看不到字段,但它们出现在文档的每个视图中。

我认为这是因为LINE 5创建了对文档该字段的引用而不是副本。这是否意味着我必须在我的所有视图中包含clone()函数才能获得我想要的内容?也许我在考虑这个错误?

更新:我使用的是CouchDB 1.0.0版并升级到1.0.1版,似乎行为已经改变。在以前的版本中,在一个视图中修改了“doc”时,修改出现在所有视图中。在最新版本中,情况似乎并非如此。

1 个答案:

答案 0 :(得分: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将对象或数组作为其属性,那么它们将只是引用,因此您必须以递归方式克隆它们。