Mongoose:CastError:强制转换为ObjectId的path“_id”的值为“”

我对node.js是新手,所以我有一种感觉,这将是我忽略的一些愚蠢的东西,但是我一直无法find解决我的问题的答案。 我想要做的是创build一个path,将创build一个新的子对象,将其添加到父项的子数组,然后将子对象返回给请求者。 我遇到的问题是,如果我将stringID传递给findById,节点崩溃

TypeError:Object {}没有方法'cast'

如果我尝试传入一个ObjectId,我会得到

CastError:在path“_id”上投射到ObjectId的值“[object Object]”失败

这是我的代码的一个粗略的轮廓:

var mongoose = require('mongoose'); var Schema = mongoose.Schema; var ObjectId = Schema.ObjectId; //Have also tried Schema.Types.ObjectId, mongoose.ObjectId mongoose.connect('mongodb://user:password@server:port/database'); app.get('/myClass/:Id/childClass/create', function(request, result) { var id = new ObjectId(request.params.Id); MyClass.findById(id).exec( function(err, myClass) { if (err || !myClass) { result.send("error: " + err + "<br>" + JSON.stringify(id) || ("object '" + request.params.Id + "' not found: " + id)); return; } var child = ChildClass(); myClass.Children.addToSet(child); myClass.save(); result.send(child); }); }); 

如果我用path“/ myClass / 51c35e5ced18cb901d000001 / childClass / create”执行这段代码,这是代码的输出:

错误:CastError:在path“_id”{“path”:“51c35e5ced18cb901d000001”,“instance”:“ObjectID”,“validators”:[],“setters”:“Castor to ObjectId” ], “吸气剂”:[], “_索引”:空}

我已经尝试使用findOne,而不是传递{_id:id},但是这看起来正是findById所做的。 我已经尝试了在其他网站上列出的ObjectId的不同类。 我已经尝试调用ObjectId()像一个函数而不是一个构造函数,并返回undefined。 在这一点上,我正在用尽想法,似乎并不是为了答复而使用Google。 任何想法,我做错了什么?

另外,就像我说的,我是node / Mongo / Mongoose / Express的新手,所以如果有更好的方法来实现我的目标,请告诉我。 我感谢所有的反馈。

编辑:

在Peter Lyons的解决方法之后,我search了另一个我正在运行的错误,并findfindByIdAndUpdate,它按预期的方式工作,正是我所希望的。 我仍然不确定为什么findById和findOne会给我这样的问题,我很想知道(也许是一个错误报告需要提交),所以我会保持开放,以防其他人有答案。

简短的回答:使用mongoose.Types.ObjectId

mongoose(但不是mongo)可以接受对象的Ids作为string,并为你“正确地投射”它们,所以只需使用:

 MyClass.findById(req.params.id) 

但是,需要注意的是,如果req.params.id不是mongo IDstring的有效格式,则会抛出一个必须捕获的exception。

所以最容易理解的是mongoose.SchemaTypes只有在定义mongoose模式时才使用,而mongoose.Types在创build要存储在数据库或查询对象中的数据对象时使用了这些东西。 因此, mongoose.Types.ObjectId("51bb793aca2ab77a3200000d")作品,会给你一个对象,你可以存储在数据库中或在查询中使用,并且如果给定一个无效的IDstring将抛出一个exception。

findOne接受查询对象并将单个模型实例传递给callback。 findById实际上是findOne({_id: id})的封装( 见这里的源代码 )。 只要find一个查询对象,并将匹配的模型实例数组传递给callback。

慢一点 这是令人困惑的,但我可以保证你在这个时候感到困惑,而不是在mongoose中碰到错误。 这是一个非常成熟的图书馆,但需要一些时间才能掌握它。

我在你的代码片段中看到的另一个可疑的事情是在实例化ChildClass时不使用new 。 除此之外,您需要发布您的架构代码,以便我们帮助您查找所有遗留的CastErrors。

对于所有那些坚持这个问题的人,但仍然无法解决这个问题:我偶然发现了同样的错误,发现_id字段是空的。

我在这里更详细地描述了它。 仍然没有find一个解决scheme,除了将_id的字段更改为非ID字段,这是一个肮脏的黑客给我。 我可能要为mongoose提交一个错误报告。 任何帮助,将不胜感激!

编辑:我更新了我的线程。 我提交了一张票,他们证实了缺less_id问题。 它将在4.xx版本中得到修复,该版本现在有一个候选版本。 rc不推荐用于生产使用!

如果你遇到这个问题,并且你正在执行某个地方的填充, 请参阅这个Mongoose问题 。

更新到Mongoose 4.0,问题已经修复。

我遇到了这个错误,这是因为id值过滤是一个无效的ObjectId格式

 const mongoose = require('mongoose'); console.log(mongoose.Types.ObjectId.isValid('53cb6b9b4f4ddef1ad47f943')); // true console.log(mongoose.Types.ObjectId.isValid('whatever')); // false 

要解决这个问题,请始终validationsearch条件值是否为有效的ObjectId

 if(params.q) { criteria.$or = [] if(mongoose.Types.ObjectId.isValid(params.id)) { criteria.$or.push({ _id: params.q }) } criteria.$or.push({ name: { $regex: params.q, $options: 'i' }}) criteria.$or.push({ email: { $regex: params.q, $options: 'i' }}) criteria.$or.push({ password: { $regex: params.q, $options: 'i' }}) } return UserModule.find(criteria).exec(() => { // do stuff }) 

我收到了这个错误CastError:创build一个模式,然后修改它,并不能追踪下来,在path“_id”投射到ObjectId失败的价值“[对象对象]”。 我删除了集合中的所有文件,我可以添加1个对象,但不是一秒钟。 我最终删除了Mongo中的集合,并且在Mongoose中重新创build了这个集合。

logging:我有这个错误,试图以一种错误的方式填写一个子文档:

 { [CastError: Cast to ObjectId failed for value "[object Object]" at path "_id"] message: 'Cast to ObjectId failed for value "[object Object]" at path "_id"', name: 'CastError', type: 'ObjectId', path: '_id' value: [ { timestamp: '2014-07-03T00:23:45-04:00', date_start: '2014-07-03T00:23:45-04:00', date_end: '2014-07-03T00:23:45-04:00', operation: 'Deactivation' } ], } 

看^ value是一个包含对象的数组:错!

说明:我以这种方式将数据从php发送到node.js API:

 $history = json_encode( array( array( 'timestamp' => date('c', time()), 'date_start' => date('c', time()), 'date_end' => date('c', time()), 'operation' => 'Deactivation' ))); 

正如你所看到的,$ history是一个包含数组的数组。 这就是为什么mongoose试图用数组而不是Scheme.ObjectId(或任何其他数据types)填充_id(或任何其他字段)。 以下工作:

 $history = json_encode( array( 'timestamp' => date('c', time()), 'date_start' => date('c', time()), 'date_end' => date('c', time()), 'operation' => 'Deactivation' )); 

我有同样的问题。发现我的Node.js已经过时了。 升级后,它的工作。

有同样的问题,我只是强迫的id到一个string。

我的模式:

 const product = new mongooseClient.Schema({ retailerID: { type: mongoose.SchemaTypes.ObjectId, required: true, index: true } }); 

然后,插入时:

 retailerID: `${retailer._id}` 

我也遇到了这个mongoose错误CastError:对于模型用户,在path\“_ id \”的值“\ n> 583fe2c488cf652d4c6b45d1 \”上投射到ObjectId失败

所以我运行npm list命令来validation我本地的mongodb和mongoose版本。 下面是报告:……
……
├──mongodb@2.2.19
├──mongoose@4.7.2
…..

似乎有这个mongodb版本的问题,所以我做的是我卸载并尝试使用不同的版本,如2.2.16

$ npm uninstall mongodb ,它会从你的node_modules目录中删除mongodb。 之后,安装较低版本的mongodb。
$ npm install mongodb@2.2.16
最后,我重新启动应用程序,CastError消失了!