Mongoose查询时如何直接将Object Id转为String?解决Next.js传参警告
解决Next.js 13 Server Component传递Mongoose查询结果到Client Component的类型问题
你遇到的问题是因为lean()虽然把Mongoose Document转为普通对象,但_id仍是ObjectId实例、date仍是Date对象,这两类对象都带有toJSON方法,不符合Next.js要求的原始类型纯对象规范。下面是几种直接可行的解决方法:
方法一:手动映射转换字段(最直接)
在查询结果返回前,手动把_id转为字符串、date转为ISO字符串(或时间戳):
async function getData() { await dbConnect() const rawData = await Weight.find().lean() // 转换每个文档的特殊字段 return rawData.map(item => ({ ...item, _id: item._id.toString(), // ObjectId转字符串 date: item.date.toISOString() // Date对象转ISO格式字符串 })) }
方法二:用MongoDB聚合查询直接转换
在数据库层面就把_id和日期转成字符串,避免前端额外处理:
async function getData() { await dbConnect() return await Weight.aggregate([ { $project: { _id: { $toString: '$_id' }, // 数据库端将ObjectId转为字符串 weight: 1, date: { $dateToString: { format: "%Y-%m-%dT%H:%M:%S", date: "$date" } }, // 自定义日期格式 __v: 1 } } ]) }
方法三:全局配置Mongoose钩子(一次配置通用)
在Weight模型的Schema里添加查询后钩子,自动转换字段,所有查询都会生效:
// 假设你的Weight Schema定义如下 const WeightSchema = new mongoose.Schema({ weight: Number, date: Date }) // 添加post查询钩子,处理find方法返回的结果 WeightSchema.post('find', function(docs) { docs.forEach(doc => { doc._id = doc._id.toString() doc.date = doc.date.toISOString() }) }) const Weight = mongoose.model('Weight', WeightSchema)
之后再调用Weight.find().lean()时,返回的结果就已经是处理好的纯原始类型对象了。
注意:如果你的查询还用到findOne等其他方法,需要对应添加findOne的post钩子。
内容的提问来源于stack exchange,提问作者Yan
相关产品推荐
相关产品推荐

