lib/object.js
function update(obj, expression){
    if(isObject(expression)) for(var key in expression){
        if(isObject(expression[key])){
            
            if(key==='$set') obj = update(obj, expression[key]);
            
            else if(key==='$inc') for(var prop in expression[key]){
                if(typeof expression[key][prop] === 'number'){
                    var orig = deepGet(obj, prop);
                    if(orig === undefined) obj = deepSet(obj, prop, expression[key][prop]);
                    else if(typeof orig === 'number') obj = deepSet(obj, prop, orig+expression[key][prop]);
                }
            }
            
            else if(key==='$max' || key==='$min') for(var prop in expression[key]){
                if(typeof expression[key][prop] === 'number'){
                    var orig = deepGet(obj, prop);
                    if(key==='$max' && orig < expression[key][prop]) obj = deepSet(obj, prop, expression[key][prop]);
                    else if(key==='$min' && orig > expression[key][prop]) obj = deepSet(obj, prop, expression[key][prop]);
                }
                
            }
            
            else if(key==='$pull' || key==='$pullAll') for(var prop in expression[key]){
                var orig = deepGet(obj, prop), value = expression[key][prop];
                if(Array.isArray(orig)){
                    if(!Array.isArray(value)) value = [value];
                    for(var i=0;i<value.length;i++){
                        var index = orig.indexOf( value[i] );
                        if(index!==-1) orig.splice(index, 1);
                    }
                    obj = deepSet(obj, prop, orig);
                }
            }
            
            else if(key==='$push') for(var prop in expression[key]){
                var orig = deepGet(obj, prop), value = expression[key][prop];
                if(value.$each) value = value.$each;
                if(Array.isArray(orig)){
                    if(!Array.isArray(value)) value = [value];
                    for(var i=0;i<value.length;i++){
                        orig.push(value[i]);
                    }
                    obj = deepSet(obj, prop, orig);
                }
            }
            
            else if(key[0]==='$') continue; // skip not recognized keys
            
            else obj = deepSet(obj, key, expression[key]); // key is simple property
        }
        
        // if expression.$set, ignore data properties outside it
        else if(!expression.$set) obj = deepSet(obj, key, expression[key]);
    }
    return obj;
}
function update(obj, expression){
    if(isObject(expression)) for(var key in expression){
        if(isObject(expression[key])){
            
            if(key==='$set') obj = update(obj, expression[key]);
            
            else if(key==='$inc') for(var prop in expression[key]){
                if(typeof expression[key][prop] === 'number'){
                    var orig = deepGet(obj, prop);
                    if(orig === undefined) obj = deepSet(obj, prop, expression[key][prop]);
                    else if(typeof orig === 'number') obj = deepSet(obj, prop, orig+expression[key][prop]);
                }
            }
            
            else if(key==='$max' || key==='$min') for(var prop in expression[key]){
                if(typeof expression[key][prop] === 'number'){
                    var orig = deepGet(obj, prop);
                    if(key==='$max' && orig < expression[key][prop]) obj = deepSet(obj, prop, expression[key][prop]);
                    else if(key==='$min' && orig > expression[key][prop]) obj = deepSet(obj, prop, expression[key][prop]);
                }
                
            }
            
            else if(key==='$pull' || key==='$pullAll') for(var prop in expression[key]){
                var orig = deepGet(obj, prop), value = expression[key][prop];
                if(Array.isArray(orig)){
                    if(!Array.isArray(value)) value = [value];
                    for(var i=0;i<value.length;i++){
                        var index = orig.indexOf( value[i] );
                        if(index!==-1) orig.splice(index, 1);
                    }
                    obj = deepSet(obj, prop, orig);
                }
            }
            
            else if(key==='$push') for(var prop in expression[key]){
                var orig = deepGet(obj, prop), value = expression[key][prop];
                if(value.$each) value = value.$each;
                if(Array.isArray(orig)){
                    if(!Array.isArray(value)) value = [value];
                    for(var i=0;i<value.length;i++){
                        orig.push(value[i]);
                    }
                    obj = deepSet(obj, prop, orig);
                }
            }
            
            else if(key[0]==='$') continue; // skip not recognized keys
            
            else obj = deepSet(obj, key, expression[key]); // key is simple property
        }
        
        // if expression.$set, ignore data properties outside it
        else if(!expression.$set) obj = deepSet(obj, key, expression[key]);
    }
    return obj;
}
/*
Update object using mongodb update query
implemented: $set, $inc, $max, $min