Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

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

Closed
dillonkrug opened this Issue · 2 comments

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
@vkarpov15
Owner

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
@vkarpov15 vkarpov15 removed this from the 3.8.23 milestone
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.