开发者

CouchDB: Adding fields to "doc" in view

In my view I want to create a new object to return instead of the object that is passed to my map function. I would like to do some validation and add some fields to the new object. My map function for the view looks like this (there isn't a 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);
    }
}

The problem is that when this view runs, it ends up adding some new fields to the documents in the database. I cannot see the fields when editing the doc in Futon, but they show up in every view of the document.

I think this is because because of LINE 5 creates a reference to that field of the document instead of a copy. Does this mean I have to include a clone() function in all my views to get what I want? Maybe I'm thinking about this wrong?

Update: I was using CouchDB version 1.0.0 and upgraded to version 1.0.1 and it开发者_StackOverflow中文版 seems that the behavior has changed. In the previous version when "doc" was modified in one view, the modification appeared in all views. In the newest version, this does not seem to be the case.


newobj = doc.someObjField does indeed make a reference and not a copy, so you'll will have to iterate over the properties of doc.someObjField and copy them over to a new object.

This is not that trivial, the following shows an example of how to make a shallow clone:

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

Your code would look like this:

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

Now if you someObjField has objects or arrays as its properties those will yet again only be references, so you have to recursively clone them.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜