You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mongoose查询用户后validate报错:createdOn日期转换失败如何解决?

问题描述

我定义了如下Mongoose Schema:

const userSchema = new mongoose.Schema({
    //...
    createdOn: {
        type: Date,
        default: Date.now,
        required: true
    },
    //...
})
const UserModel = mongoose.model('User', userSchema)

但当我通过模型查询用户并验证时:

const user = await UserModel.findById('65dbf8b2a9a4828a79317571')
try {
    await user.validate()
} catch (err) {
    console.log(JSON.stringify(err))
}

在createdOn属性上出现如下错误:

{
  "errors": {
    "createdOn": {
      "name": "ValidatorError",
      "message": "Cast to date failed for value \"{ '$date': '2023-05-26T09:53:22-03:00' }\" (type Object) at path \"createdOn\"",
      "properties": {
        "path": "createdOn",
        "message": "Cast to date failed for value \"{ '$date': '2023-05-26T09:53:22-03:00' }\" (type Object) at path \"createdOn\"",
        "type": "cast",
        "value": {
          "$date": "2023-05-26T09:53:22-03:00"
        },
        "reason": {
          "stringValue": "\"{ '$date': '2023-05-26T09:53:22-03:00' }\"",
          "valueType": "Object",
          "kind": "date",
          "value": {
            "$date": "2023-05-26T09:53:22-03:00"
          },
          "path": "createdOn",
          "reason": {
            "generatedMessage": true,
            "code": "ERR_ASSERTION",
            "actual": false,
            "expected": true,
            "operator": "=="
          },
          "name": "CastError",
          "message": "Cast to date failed for value \"{ '$date': '2023-05-26T09:53:22-03:00' }\" (type Object) at path \"createdOn\""
        }
      },
      "kind": "cast",
      "path": "createdOn",
      "value": {
        "$date": "2023-05-26T09:53:22-03:00"
      },
      "reason": {
        "stringValue": "\"{ '$date': '2023-05-26T09:53:22-03:00' }\"",
        "valueType": "Object",
        "kind": "date",
        "value": {
          "$date": "2023-05-26T09:53:22-03:00"
        },
        "path": "createdOn",
        "reason": {
          "generatedMessage": true,
          "code": "ERR_ASSERTION",
          "actual": false,
          "expected": true,
          "operator": "=="
        },
        "name": "CastError",
        "message": "Cast to date failed for value \"{ '$date': '2023-05-26T09:53:22-03:00' }\" (type Object) at path \"createdOn\""
      }
    }
  },
  "_message": "User validation failed",
  "name": "ValidationError",
  "message": "User validation failed: createdOn: Cast to date failed for value \"{ '$date': '2023-05-26T09:53:22-03:00' }\" (type Object) at path \"createdOn\""
}

请问我哪里操作有误?该如何修复这个问题?

问题分析与修复

原因

数据库中createdOn字段存储的是MongoDB扩展JSON格式({ "$date": "..." }),而非标准Date对象。这种情况通常是数据未通过Mongoose写入,而是直接用MongoDB客户端、其他工具或旧代码插入,导致Mongoose查询后无法自动转换为Date类型,触发验证时的类型转换错误。

修复方案

方案1:批量更新现有数据

直接在MongoDB中将所有createdOn字段从{ "$date": "..." }格式转为标准Date类型:

await UserModel.updateMany(
  { createdOn: { $type: "object" } }, // 匹配对象类型的createdOn
  [
    {
      $set: {
        createdOn: { $toDate: "$createdOn.$date" }
      }
    }
  ]
);

执行后,现有数据的createdOn会转为标准Date,后续查询验证即可正常进行。

方案2:在Schema中添加自定义转换器

若无法修改现有数据,可给createdOn字段添加自定义getter和setter,自动处理格式转换:

const userSchema = new mongoose.Schema({
    //...
    createdOn: {
        type: Date,
        default: Date.now,
        required: true,
        get: function(value) {
          // 读取时若为$date格式对象,转为Date
          if (typeof value === 'object' && value.$date) {
            return new Date(value.$date);
          }
          return value;
        },
        set: function(value) {
          // 写入时确保转为Date
          if (typeof value === 'object' && value.$date) {
            return new Date(value.$date);
          }
          return value;
        }
    },
    //...
})
// 开启getters,确保查询时转换器生效
userSchema.set('toObject', { getters: true });
userSchema.set('toJSON', { getters: true });

const UserModel = mongoose.model('User', userSchema)

这样无论读写操作,都会自动处理$date格式的对象,验证时可正常识别为Date类型。

方案3:验证前手动转换(临时解决)

如果只是临时处理单个查询的验证问题,可在调用validate()前手动转换createdOn的值:

const user = await UserModel.findById('65dbf8b2a9a4828a79317571')
// 手动转换格式
if (user.createdOn && typeof user.createdOn === 'object' && user.createdOn.$date) {
  user.createdOn = new Date(user.createdOn.$date);
}
try {
    await user.validate()
} catch (err) {
    console.log(JSON.stringify(err))
}

内容的提问来源于stack exchange,提问作者user20416

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 06:55:14