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
相关产品推荐
相关产品推荐

