Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Cast to ObjectId failed" for custom ID and $elemMatch/$not #3719

Closed
parisholley opened this issue Dec 29, 2015 · 5 comments
Closed

"Cast to ObjectId failed" for custom ID and $elemMatch/$not #3719

parisholley opened this issue Dec 29, 2015 · 5 comments
Labels
can't reproduce Mongoose devs have been unable to reproduce this issue. Close after 14 days of inactivity.

Comments

@parisholley
Copy link

Here is an example schema

var child = new mongoose.Schema({
    _id: {type: String}
});

var parent = new mongoose.Schema({
    children: [child]
});

The following query has been abbreviated to exclude the non-relevant info (my query is quite large). When $elemMatch is used without $not, it works fine and can cast the _id. However, when placed within a $not{} tag, it tries to cast as ObjectID and fails.

model.find({
    $and: [{
        $or: [{
            $and: [
                {
                    myField: {
                        $not: {
                            $elemMatch: {
                                _id: 'customString'
                            }
                        }
                    }
                }
            ]
        }]
    }]
})
@vkarpov15 vkarpov15 added this to the 4.3.5 milestone Jan 4, 2016
@vkarpov15
Copy link
Collaborator

Hmm that's strange, the below script executes without error for me against 4.3.4:

var assert = require('assert');
var mongoose = require('mongoose');

mongoose.set('debug', true);
mongoose.connect('mongodb://localhost:27017/gh3719');

var child = new mongoose.Schema({
    _id: {type: String}
});

var parent = new mongoose.Schema({
    children: [child]
});

var Parent = mongoose.model('Parent', parent);

Parent.create({ children: [{ _id: 'customString' }] }, function(error) {
  assert.ifError(error);
  test();
});

function test() {
  Parent.find({
      $and: [{
          $or: [{
              $and: [
                  {
                      myField: {
                          $not: {
                              $elemMatch: {
                                  _id: 'customString'
                              }
                          }
                      }
                  }
              ]
          }]
      }]
  }, function(error, docs) {
    assert.ifError(error);
    assert.ok(docs.length > 0);
    process.exit(0);
  });
}
$ node gh-3719.js 
Mongoose: parents.insert({ _id: ObjectId("568c46067ab8da0728640c4d"), children: [ { _id: 'customString' } ], __v: 0 })   
Mongoose: parents.find({ '$and': [ { '$or': [ { '$and': [ { myField: { '$not': { '$elemMatch': { _id: 'customString' } } } } ] } ] } ] }) { fields: undefined }

Can you check if the above script works for you and confirm which version of mongoose you're using?

@vkarpov15 vkarpov15 added the can't reproduce Mongoose devs have been unable to reproduce this issue. Close after 14 days of inactivity. label Jan 5, 2016
@vkarpov15 vkarpov15 modified the milestones: 4.3.6, 4.3.5 Jan 7, 2016
@vkarpov15 vkarpov15 modified the milestones: 4.3.7, 4.3.6 Jan 16, 2016
@vkarpov15
Copy link
Collaborator

Issue's gone stale. Re-open if this is still an issue.

@vkarpov15 vkarpov15 removed this from the 4.3.7 milestone Jan 20, 2016
@timbowhite
Copy link

I'm able to reproduce this issue. Popped up after upgrading from 3.28.x to 4.6.0. Node v.6.5.0. Example:

'use strict';

var assert = require('assert');
var mongoose = require('mongoose');

mongoose.set('debug', true);
mongoose.connect('mongodb://localhost:27017/gh3719');

var child = new mongoose.Schema({
    _id: {type: String}
}, {_id: false});

var parent = new mongoose.Schema({
  children: [child]
});

var Parent = mongoose.model('Parent', parent);

Parent.create({children: [{ _id: 'customString' }] }, function(error) {
  assert.ifError(error);
  test();
});

function test() {
  Parent.find({
      $and: [{children: {$not: {$elemMatch: {_id: 'foobar'}}}}]
  }, function(error, docs) {
    assert.ifError(error);
    assert.ok(docs.length > 0);
    process.exit();
  });
}

Yields:

Mongoose: parents.insert({ _id: ObjectId("57db6b41f3c2cb191aee60a1"), children: [ { _id: 'customString' } ], __v: 0 })
events.js:160
      throw er; // Unhandled 'error' event
      ^
CastError: Cast to ObjectId failed for value "foobar" at path "_id"
    at MongooseError.CastError (/.../node_modules/mongoose/lib/error/cast.js:26:11)
    at ObjectId.cast (/.../node_modules/mongoose/lib/schema/objectid.js:147:13)
    at ObjectId.castForQuery (/.../node_modules/mongoose/lib/schema/objectid.js:187:15)
    ...

The query works if the $not is removed, ie:

$and: [{children: {$elemMatch: {_id: 'foobar'}}}]

@timbowhite
Copy link

Seems like possible fix could be changing line 206 of lib/cast.js from

if ($cond === '$not') {
  cast(schema, nested);
} else {

to

if ($cond === '$not') {
  cast(schematype.caster.schema, nested);
} else {

timbowhite pushed a commit to timbowhite/mongoose that referenced this issue Sep 16, 2016
@timbowhite
Copy link

I think #4531 fixes this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
can't reproduce Mongoose devs have been unable to reproduce this issue. Close after 14 days of inactivity.
Projects
None yet
Development

No branches or pull requests

3 participants