在未定义/空子文档 ObjectId 字段上设置值会产生 Cast to ObjectId 错误

Posted

技术标签:

【中文标题】在未定义/空子文档 ObjectId 字段上设置值会产生 Cast to ObjectId 错误【英文标题】:Setting a value on an undefined/null sub-document ObjectId field produces Cast to ObjectId error 【发布时间】:2015-04-25 19:24:50 【问题描述】:

在 MEAN.js 应用程序中,我有一个包含子文档参考的架构:

var EmployeeSchema = new Schema(
    supervisor: 
        type: Schema.Types.ObjectId, 
        ref: 'User',
    ,
    ... 

无论是否设置主管字段,我都可以从架构创建模型。如果值是在创建时设置的,那么我可以像这样取消设置:

employee.supervisor = undefined;

employee.save(function(err) 
...

但是,如果字段值已经未定义,那么此后我将无法设置任何值 - 这会产生以下错误:

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

实际上,使用相同的 .save 代码路径再次尝试将该值设置为 undefined 会导致相同的错误。这个错误来自哪里?它所指的这个对象是什么(当我向它发送一个未定义的值时)?

我对猫鼬比较陌生。这感觉像是一个基本问题,很可能是用户错误。如果我没有使用正确的模式,请告诉我。我使用的是 mongoose 3.8.8,然后我搬到了 3.8.23,但无济于事。

编辑:可能很重要的一点是,当员工返回客户时,主管会被填充。使用 MEAN 样板快速控制器进行更新似乎存在问题,它将更改状态的 _.assign 分配给发送给客户端的 req.employee 数据。

如果我再次手动查询员工,并设置/取消设置主管字段,那么我能够获得预期的行为而不会出现错误。这包括设置为未定义,以及设置回一个有效值。所以它归结为人口 + 使用请求数据执行更新的组合。

【问题讨论】:

【参考方案1】:

我认为这是因为 undefined 未通过 Schema.Types.ObjectId 验证。您应该使用 $unset

Employee.update(
  //whatever query
,

  $unset:  supervisor: true 
,
 multi: true)

【讨论】:

根据link,未定义+保存相当于更新+未设置。不是这样吗?

以上是关于在未定义/空子文档 ObjectId 字段上设置值会产生 Cast to ObjectId 错误的主要内容,如果未能解决你的问题,请参考以下文章

Mongoose:在设置值后,新创建的对象上的值转换为 ObjectId 失败 [重复]

Vue 警告我无法在未定义、null 或原始值上设置反应属性:null

MongoDB索引的唯一性值

Apollo graphql 正在为 mongodb 中的空子文档返回空数据

Apollo GraphQL 客户端“网络错误:在未定义的对象上找不到字段 XXXX”,disableOffline:false

在 mongodb 中删除所有 ObjectId 类型的文档作为 _id 字段