node.js Mongoose:CastError:Cast to ObjectId 在路径“_id”处的值“[object Object]”失败

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17223517/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 14:51:46  来源:igfitidea点击:

Mongoose: CastError: Cast to ObjectId failed for value "[object Object]" at path "_id"

node.jsmongodbmongoose

提问by jmblackmer

I am new to node.js, so I have a feeling that this will be something silly that I have overlooked, but I haven't been able to find an answer that fixes my problem. What I'm trying to do is create a path that will create a new child object, add it to the parent's array of children, then return the child object to the requester. The problem that I am running into is that if I pass the string id into findById, node crashes with

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

TypeError: Object {} has no method 'cast'

类型错误:对象 {} 没有方法“cast”

If I try to pass in an ObjectId instead, I get

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

CastError: Cast to ObjectId failed for value "[object Object]" at path "_id"

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

Here is a rough outline of my code:

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

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

If I execute this code with the path "/myClass/51c35e5ced18cb901d000001/childClass/create", this is the output of the code:

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

error: CastError: Cast to ObjectId failed for value "[object Object]" at path "_id" {"path":"51c35e5ced18cb901d000001","instance":"ObjectID","validators":[],"setters":[],"getters":[],"_index":null}

错误:CastError:在路径“_id”{“path”:“51c35e5ced18cb901d000001”,“instance”:“ObjectID”,“validators”:[],“setters”:[ ],"getters":[],"_index":null}

I've tried using findOne and passing in {_id:id} instead, but this appears to be exactly what findById does. I've tried the different classes for ObjectId that I've seen listed on other sites. I've tried calling ObjectId() like a function instead of a constructor and that returns undefined. At this point, I'm running out of ideas and it doesn't seem that googling for an answer is helping. Any ideas on what I'm doing wrong?

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

Also, like I said, I'm new to node/Mongo/Mongoose/Express, so if there is a better way to accomplish my goal, please let me know. I appreciate all feedback.

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

EDIT:

编辑:

After the workaround from Peter Lyons, I googled another error that I was running into and found findByIdAndUpdate, which works as expected and does exactly what I was hoping to do. I'm still not sure why findById and findOne were giving me such issues and I'm curious to know (maybe a bug report needs to be filed), so I'll leave this open in case someone else has an answer.

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

回答by Peter Lyons

Short answer: use mongoose.Types.ObjectId.

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

Mongoose (but not mongo) can accept object Ids as strings and "cast" them properly for you, so just use:

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

MyClass.findById(req.params.id)

However, the caveat is if req.params.idis not a valid format for a mongo ID string, that will throw an exception which you must catch.

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

So the main confusing thing to understand is that mongoose.SchemaTypeshas stuff you only use when defining mongoose schemas, and mongoose.Typeshas the stuff you use when creating data objects you want to store in the database or query objects. So mongoose.Types.ObjectId("51bb793aca2ab77a3200000d")works, will give you an object you can store in the database or use in queries, and will throw an exception if given an invalid ID string.

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

findOnetakes a query object and passes a single model instance to the callback. And findByIdis literally a wrapper of findOne({_id: id})(see source code here). Just findtakes a query object and passes an array of matching model instances to the callback.

findOne接受一个查询对象并将单个模型实例传递给回调。并且findById实际上是findOne({_id: id})请参阅此处的源代码)的包装器。只find需要一个查询对象并将一组匹配的模型实例传递给回调。

Just go slow. It's confusing but I can guarantee you you are getting confused and not hitting bugs in mongoose at this point. It's a pretty mature library, but it takes some time to get the hang of it.

慢慢来吧。这很令人困惑,但我可以向您保证,此时您会感到困惑并且不会在 mongoose 中遇到错误。这是一个相当成熟的库,但需要一些时间来掌握它。

The other suspect thing I see in your snippet is not using newwhen instantiating ChildClass. Beyond that, you'll need to post your schema code in order for us to help you tract down any CastErrors that remain.

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

回答by gsalgadotoledo

I've faced this error, That was because the value you want to filter in the _id field is not in an ID format, one "if" should solve your error.

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

const mongoose = require('mongoose');

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

To solve it, always validate if the criteria value for search is a valid ObjectId

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

回答by Stefan Medack

For all those people stuck with this problem, but still couldn't solve it: I stumbled upon the same error and found the _idfield being empty.

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

I described it herein more detail. Still have not found a solution except changing the fields in _idto not-ID fields which is a dirty hack to me. I'm probably going to file a bug report for mongoose. Any help would be appreciated!

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

Edit: I updated my thread. I filed a ticket and they confirmed the missing _idproblem. It is going to be fixed in the 4.x.x version which has a release candidate available right now. The rc is not recommended for productive use!

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

回答by ac360

If you are having this issue and you are performing a populate somewhere along the lines, see this Mongoose issue.

如果您遇到此问题并且您正在沿线某处执行填充,请参阅此猫鼬问题

Update to Mongoose 4.0 and the issue has been fixed.

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

回答by camstuart

Had the same problem, I just coerced the id into a string.

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

My schema:

我的架构:

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

And then, when inserting:

然后,插入时:

retailerID: `${retailer._id}`

回答by Enkode

I was receiving this error CastError: Cast to ObjectId failed for value “[object Object]” at path “_id” after creating a schema, then modifying it and couldn't track it down. I deleted all the documents in the collection and I could add 1 object but not a second. I ended up deleting the collection in Mongo and that worked as Mongoose recreated the collection.

我在创建模式后收到此错误 CastError: Cast to ObjectId failed for value “[object Object]” at path “_id”,然后修改它并且无法追踪它。我删除了集合中的所有文档,我可以添加 1 个对象,但不能添加一秒钟。我最终删除了 Mongo 中的集合,并且在 Mongoose 重新创建了该集合时起作用了。

回答by Igor Parra

For the record: I had this error trying to fill a subdocument in a wrong way:

作为记录:我试图以错误的方式填充子文档时遇到此错误:

{
[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 is an array containing an object: wrong!

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

Explanation: I was sending data from php to a node.js API in this way:

说明:我以这种方式从 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'
)));

As you can see $history is an array containing an array. That's why mongoose try to fill _id (or any other field) with an array instead than a Scheme.ObjectId (or any other data type). The following works:

如您所见, $history 是一个包含数组的数组。这就是为什么猫鼬尝试用数组而不是 Scheme.ObjectId(或任何其他数据类型)填充 _id(或任何其他字段)的原因。以下工作:

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

回答by happyCoder

just change the path it will work for example

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

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

change to

改成

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

I just added --es-- to the path (myClass) to become (myClasses)

我刚刚将 --es-- 添加到路径 (myClass) 以变为 (myClasses)

now should work and will not see that error

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

回答by Jazeb_007

My solution is that i want data from all docs and i dont want _id, so

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

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

回答by Jorge Pires

I had the same problem, turned out after I have updated my schema, I have forgotten I was calling the model using the old id, which was created by me; I have updated my schema from something like:

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

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

to

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

It turned out, since my code is big, I was calling the findOnewith the old id, therefore, the problem.

事实证明,由于我的代码很大,所以我findOne使用旧 ID调用了,因此,问题出在了。

I am posting here just to help somebody else: please, check your code for unknown wrong calls! it may be the problem, and it can save your huge headacles!

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