猫鼬:CastError:在路径“ _id”中,值“ [object Object]”的对象转换为ObjectId失败


74

我是node.js的新手,所以我觉得这将是我忽略的愚蠢之举,但我一直无法找到解决问题的答案。我想做的是创建一个路径,该路径将创建一个新的子对象,将其添加到父对象的子对象数组中,然后将该子对象返回给请求者。我遇到的问题是,如果我将字符串ID传递给findById,节点将崩溃

TypeError:对象{}没有方法“ cast”

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

CastError:对于路径“ _id”中的值“ [object Object]”,转换为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” {“ path”:“ 51c35e5ced18cb901d000001”,“ instance”:“ ObjectID”,“ validators”:[],“ setters”:[ ],“ getters”:[],“ _ index”:null}

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

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

编辑:

经过Peter Lyons的解决方法之后,我用谷歌搜索了我遇到的另一个错误,并找到了findByIdAndUpdate,它可以按预期运行,并且完全符合我的期望。我仍然不确定为什么findById和findOne会给我这样的问题,并且我很想知道(也许需要提交错误报告),所以我会在其他人有答案的情况下保持此状态。


我的猜测是您只findOne用一个调用,ObjectId但是findOne期望键/值条件的常规JS对象。
里昂

我已经在这里回答了这些问题。
截至

1
检查您的路线。可能是两条路由具有相同的起点示例“ #GET / user /:userID和#GET / user / list”。该路由将使用“列表”作为数据库的输入,并且会出现一些错误。
Jose Hernandez

Answers:


72

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

猫鼬(但不是mongo)可以接受对象ID作为字符串,并为您正确地“投射”它们,因此只需使用:

MyClass.findById(req.params.id)

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

因此,最令人困惑的是,mongoose.SchemaTypes只有在定义猫鼬模式时才使用mongoose.Types的东西,而在创建要存储在数据库或查询对象中的数据对象时才使用的东西。如此mongoose.Types.ObjectId("51bb793aca2ab77a3200000d")有效,将为您提供一个可以存储在数据库中或在查询中使用的对象,并且如果给出无效的ID字符串,则将引发异常。

findOne接受一个查询对象,并将单个模型实例传递给回调。而且findById是名副其实的包装findOne({_id: id})见源代码在这里)。只是find获取一个查询对象,并将匹配的模型实例数组传递给回调。

慢慢来。这很令人困惑,但我可以保证您现在会感到困惑,并且不会遇到猫鼬中的错误。这是一个相当成熟的库,但是要花点时间才能掌握。

我在您的代码段中看到的另一个可疑的东西是new在实例化时没有使用ChildClass。除此之外,您还需要发布架构代码,以便我们帮助您减少剩余的CastError。


如果我尝试使用“ mongoose.Types.ObjectId(“ 51c35e5ced18cb901d000001”);“ (通过直接将其放置在代码中),我仍然收到错误“ TypeError:对象{}没有方法'cast'”。我也尝试将其实例化为一个对象,并得到相同的错误。
jmblackmer

升级到最新的猫鼬?我在3.6.11。
Peter Lyons 2013年

调用MyClass.find(req.params.id)是可行的。findOne和findById是否应该以相同的方式工作?看起来当其他两个存在时返回单个文档的函数看起来有点违反直觉。我已经更改了代码,现在可以获取数组的第一项,但是现在在addToSet()上失败,出现“ TypeError:Object {}没有方法'cast'”。
jmblackmer

我也在3.6.11上。我只是在前一天晚上设置了所有这些内容,所以我希望所有内容都已更新。
jmblackmer

1
您使用了错误的构造函数。使用mongoose.Types.ObjectIdmongoose.Schema.ObjectId仅用于定义架构。
彼得·里昂斯

44

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

const mongoose = require('mongoose');

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

要解决此问题,请始终验证搜索条件值是否为有效的ObjectId

const criteria = {};
criteria.$or = [];

if(params.q) {
  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
})

3
正确。我正在使用来测试GET用户的端点findById,结果证明id参数必须为12位,否则猫鼬将无法转换。我正在使用随机短号。
10110

3

对于所有困扰这个问题,但仍然无法解决的人:我偶然发现了相同的错误,发现该_id字段为空。

在这里更详细地描述了它。除了将字段更改_id为非ID字段外,仍未找到解决方案,这对我来说是一个肮脏的技巧。我可能要提交猫鼬的错误报告。任何帮助,将不胜感激!

编辑:我更新了我的线程。我提交了一张票,他们确认了缺失的_id问题。它会在4.xx版本中修复,该版本现在有可用的候选版本。不建议将rc用于生产性使用!


有趣的是,我认为我也有同样的问题,我的_id是未定义的,因此无法转换为ObjectId
Alexander Mills


2

遇到相同的问题,我只是将id强制为字符串。

我的架构:

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

然后,在插入时:

retailerID: `${retailer._id}`

1

我收到此错误CastError:创建模式,然后对其进行修改并无法对其进行跟踪后,在路径“ _id”中将值“ [object Object]”的对象强制转换为ObjectId失败。我删除了集合中的所有文档,可以添加1个对象,但不能添加第二个对象。我最终在Mongo中删除了该集合,这在Mongoose重新创建该集合时起作用。


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是一个包含数组的数组。这就是为什么猫鼬会尝试用数组而不是Scheme.ObjectId(或任何其他数据类型)填充_id(或任何其他字段)的原因。以下作品:

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

1

我还遇到了此猫鼬错误CastError:模型用户的路径\ __ id \上的值\“ 583fe2c488cf652d4c6b45d1 \”强制转换为ObjectId

所以我运行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消失了!!



1

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

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

0

只需更改它将起作用的路径,例如

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

改成

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

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

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


0

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

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

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

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

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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.