Mongoose:CastError:对于路径“_id”的值“[object Object]”,转换为ObjectId失败

时间:2013-06-20 20:50:17

标签: node.js mongodb mongoose

我是node.js的新手,所以我有一种感觉,这将是一些我忽略的愚蠢,但我找不到能解决问题的答案。我要做的是创建一个路径,创建一个新的子对象,将其添加到父的子数组,然后将子对象返回给请求者。我遇到的问题是,如果我将字符串id传递给findById,节点崩溃

  

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

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

  

CastError:对于路径“_id”的值“[object Object]”,Cast to ObjectId失败

以下是我的代码的大致轮廓:

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);
  });
});

如果我使用路径“/ myClass / 51c35e5ced18cb901d000001 / childClass / create”执行此代码,则这是代码的输出:

  

错误:CastError:对于路径“_id”处的值“[object Object]”,转换为ObjectId失败   { “路径”: “51c35e5ced18cb901d000001”, “实例”: “的ObjectID”, “验证”:[] “制定者”:[], “吸气剂”:[], “_索引”:空}

我尝试过使用findOne并传入{_id:id},但这似乎正是findById所做的。我已经尝试过我在其他网站上列出的ObjectId的不同类。我试过调用ObjectId()就像一个函数而不是一个构造函数,并返回undefined。在这一点上,我已经没有想法,谷歌搜索答案似乎没有帮助。关于我做错了什么想法?

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

修改

在Peter Lyons的解决方法之后,我搜索了我遇到的另一个错误,找到了findByIdAndUpdate,它按预期工作,完全符合我的希望。我仍然不确定为什么findById和findOne给我这样的问题而且我很想知道(可能需要提交错误报告),所以我会保持这个问题以防其他人有答案。

13 个答案:

答案 0 :(得分:61)

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

Mongoose(但不是mongo)可以接受对象ID作为字符串并为你正确地“转换”它们,所以只需使用:

MyClass.findById(req.params.id)

但是,需要注意的是,如果req.params.id不是mongo ID字符串的有效格式,则会抛出必须捕获的异常。

因此,要理解的主要问题是mongoose.SchemaTypes具有仅在定义mongoose模式时使用的内容,而mongoose.Types具有您在创建要存储在数据库中的数据对象时使用的内容或查询对象。因此,mongoose.Types.ObjectId("51bb793aca2ab77a3200000d")可以为您提供一个可以存储在数据库中或在查询中使用的对象,如果给出了无效的ID字符串,则会抛出异常。

findOne接受查询对象并将单个模型实例传递给回调。而findById实际上是findOne({_id: id})see source code here)的包装。 Just find接受一个查询对象,并将一组匹配的模型实例传递给回调。

慢慢走。这令人困惑,但我可以保证你会感到困惑,而不是在猫鼬中遇到错误。它是一个非常成熟的库,但它需要一些时间才能掌握它。

我在代码段中看到的另一个可疑内容是在实例化new时未使用ChildClass。除此之外,您还需要发布您的架构代码,以便我们帮助您解决任何剩余的CastErrors。

答案 1 :(得分:21)

我遇到了这个错误,那是因为你要在_id字段中过滤的值不是ID格式,一个“if”应该解决这个问题。

const mongoose = require('mongoose');

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

要解决此问题,请始终验证搜索的条件值是否为有效的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
})

答案 2 :(得分:2)

如果您遇到此问题,并且正在执行填充,see this Mongoose issue

更新到Mongoose 4.0并且问题已修复。

答案 3 :(得分:2)

出现同样的问题,我只是将id强制转换为字符串。

我的架构:

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

然后,插入时:

retailerID: `${retailer._id}`

答案 4 :(得分:1)

我收到此错误CastError:在创建架构后,路径“_id”处的值为“[object Object]”时,Cast to ObjectId失败,然后修改它并且无法跟踪它。我删除了集合中的所有文档,我可以添加1个对象,但不能添加第二个。我最终删除了Mongo中的集合,并且当Mongoose重新创建集合时起作用。

答案 5 :(得分:1)

对于记录:我在尝试以错误的方式填充子文档时遇到此错误:

{
[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' } ],
}

look ^ 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(或任何其他数据类型)填充_id(或任何其他字段)的原因。以下作品:

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

答案 6 :(得分:1)

我遇到了同样的问题。转出我的Node.js已经过时了。升级后它正在运行。

答案 7 :(得分:0)

我也遇到过这个猫鼬错误CastError:对于路径值为“583fe2c488cf652d4c6b45d1 \”而言,施放到ObjectId失败  模型用户

的“_ id \”

所以我运行npm list命令来验证我本地的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消失了!!

答案 8 :(得分:0)

仅更改其将起作用的路径

*char[]

更改为

app.get('/myClass/:Id/childClass/create', function(request, result) .....

我刚刚在路径(myClass)中添加了--es--成为(myClasses)

现在应该可以工作,不会看到该错误

答案 9 :(得分:0)

我的解决方案是我想要所有文档中的数据,而不想要_id,所以

User.find({}, {_id:0, keyToShow:1, keyToNotShow:0})

答案 10 :(得分:0)

我遇到了同样的问题,更新了架构后,我忘记了我是使用由我创建的旧ID调用模型的;我已经从类似以下内容更新了架构:

patientid: {
           type: String,
            required: true,
            unique: true
          }, 

patientid: { type: mongoose.SchemaTypes.ObjectId, ref: "Patient" },

原来,由于我的代码很大,所以我用旧ID调用findOne,因此是问题所在。

我在这里发布的只是为了帮助其他人:请检查您的代码中是否有未知的错误呼叫!这可能是问题所在,并且可以节省您的巨大麻烦!

答案 11 :(得分:0)

我不确定这是否有帮助,但是我通过如下所示导入猫鼬并按如下所示实施了此问题

const mongoose = require('mongoose')

_id: new mongoose.Types.ObjectId(),

答案 12 :(得分:0)

对我来说,ID 未定义(req.params.id 返回未定义)