Mongoose配合TypeScript查询MongoDB返回_id格式异常问题
问题根因
你看到的_id格式是BSON ObjectId的原始底层结构,触发原因是你调用了.lean()方法:该方法会让Mongoose跳过文档实例的序列化封装逻辑,直接返回数据库查询得到的原始BSON对象,不会自动把ObjectId类型转为常用的24位十六进制字符串。
解决方案
方案1:调整lean查询参数(最快解决)
开启lean的getters配置,让Mongoose保留字段的默认转换逻辑,自动把ObjectId转为字符串:
await ProjectModel.find({ owner: 13 }) .select("-__v") .lean({ getters: true }) .exec();
方案2:Schema全局配置(统一管控返回格式)
给两个Schema添加toJSON转换配置,所有返回JSON的场景都会自动处理_id格式,不用每次查询单独配置:
// ModuleSchema 和 ProjectSchema 都添加以下配置 export const ModuleSchema = new mongoose.Schema({ // 原有字段配置不变 }, { toJSON: { transform: (_, ret) => { // 直接把_id转为字符串,或者也可以改成返回id字段删掉_id ret._id = ret._id.toString(); return ret; } } });
方案3:手动转换结果(适配特殊场景)
如果上述方案不符合你的业务逻辑,可写递归函数手动转换所有ObjectId字段:
function transformObjectIds(data: any) { if (Array.isArray(data)) return data.map(item => transformObjectIds(item)); if (data?._bsontype === "ObjectID") return data.toString(); if (typeof data === "object" && data !== null) { return Object.fromEntries( Object.entries(data).map(([k, v]) => [k, transformObjectIds(v)]) ); } return data; } // 查询后调用转换即可 const rawResult = await ProjectModel.find({ owner: 13 }).select("-__v").lean().exec(); const formattedResult = transformObjectIds(rawResult);
额外类型优化建议
你使用.lean()后返回的是纯JS对象,不是Mongoose的Document实例,所以现有继承了Document的接口类型和实际返回结果不匹配,可以单独定义lean返回的专属类型:
export interface IModuleLean { _id: string; name: string; owner: number; isMain: boolean; url: string; } export interface IProjectLean { _id: string; name: string; description: string; owner: number; modules: IModuleLean[]; }
内容的提问来源于stack exchange,提问作者Stefan Stoychev
相关产品推荐
相关产品推荐

