doc.update with $pull (or any other operator) getting mangled by strict mode. #1947

Closed
dillonkrug opened this Issue Mar 6, 2014 · 2 comments

Projects

None yet

2 participants

@dillonkrug

This isn't working in many cases:

document.update({
    $pull: { field: { <query> } }
});

judging by the code (/lib/query.js around line 1921: schema = '$each' === key), any operator other than $each will get removed ($or, $and, $elemMatch, etc...).

When strict mode is set to false it works properly.
If strict was set to "throw", the error 'Field "foo.$or" is not in schema.' would be returned.

Full reproduction:

var mongoose = require('mongoose');
mongoose.connect('localhost:27017/test');
var Model = mongoose.model('Model', {
    foo: [new mongoose.Schema({
        bar: String,
        baz: Number
    })]
});

Model.create({
    foo: [
        {bar: 'test1', baz: 1 }, 
        {bar: 'test2', baz: 2 }, 
        {bar: 'test3', baz: 5 }
    ]
}, function(err, doc) {
    doc.update({
        $pull: {
            foo: {
                $or: [ { bar: 'test1' }, { baz: { $gt: 2 } } ]
            }
        }
    }, function(err, numModified) {
        console.log(err, numModified) // -> null, 0 (no update happened because the update was rewritten to noop)
        Model.findOne(function(err, doc) {
            console.log(doc.foo.length) // -> 3 (confirmation that no update happened.)
        })
    })
});
@dillonkrug

This also doesn't work:

Model.update({}, {
    $pull: {
        foo: {
            $or: [ { bar: 'test1' }, { baz: { $gt: 2 } } ]
        }
    }
}, function(err){ ... })
@vkarpov15 vkarpov15 added this to the 3.8.23 milestone Feb 4, 2015
@vkarpov15
Collaborator

This was fixed in 3.8.15, see #1932. The below code:

var mongoose = require('mongoose');
mongoose.connect('localhost:27017/test');
var Model = mongoose.model('Model', {
    foo: [new mongoose.Schema({
        bar: String,
        baz: Number
    })]
});

Model.create({
    foo: [
        {bar: 'test1', baz: 1 }, 
        {bar: 'test2', baz: 2 }, 
        {bar: 'test3', baz: 5 }
    ]
}, function(err, doc) {
    doc.update({
        $pull: {
            foo: {
                $or: [ { bar: 'test1' }, { baz: { $gt: 2 } } ]
            }
        }
    }, function(err, numModified) {
        console.log(err, numModified) // -> null, 0 (no update happened because the update was rewritten to noop)
        Model.findOne({ _id: doc._id }, function(err, doc) {
            console.log(doc.foo.length) // -> 3 (confirmation that no update happened.)
        })
    })
});

Outputs

null 1
1

As expected in 3.8.15, rather than 0/3 as in 3.8.14.

@vkarpov15 vkarpov15 closed this Feb 4, 2015
@vkarpov15 vkarpov15 removed this from the 3.8.23 milestone Feb 4, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment