MongoDB/Mongoose查询如何提取ObjectId中的纯字符串ID值
Mongoose+TypeScript 提取_id纯字符串的正确方法
首先说明两个代码误区:
Model.findById()入参直接接收文档ID字符串即可,不需要额外包装为{_id: id}格式的查询对象,多余的包装会导致查询逻辑异常、TS类型报错。- Mongoose默认返回的查询结果是Mongoose文档实例,其上的
_id字段是ObjectId类型实例,并非字符串类型,直接取值会拿到带ObjectId包装的对象,需要调用内置转换方法才能拿到纯字符串ID。
可用实现方案
- 方案1:调用ObjectId自带的
toString()方法,适配所有场景
async findById(id: string) { // 直接传入id字符串查询 const userDoc = await userModel.findById(id); // 调用toString()即可拿到"62aa4bddae588fb13e8df552"格式的纯字符串ID const pureId = userDoc?._id?.toString(); // 后续直接使用pureId做存储、传参即可 return pureId; }
- 方案2:使用Mongoose文档默认自带的
id虚拟属性,写法更简洁
Mongoose为所有文档实例默认挂载了idgetter属性,直接取值就能得到_id对应的十六进制字符串,不需要手动调用转换方法:
async findById(id: string) { const userDoc = await userModel.findById(id); // 直接取id属性,就是纯字符串格式的文档ID const pureId = userDoc?.id; return pureId; }
- 方案3:全局配置Schema转换,查询直接返回_id为字符串的纯对象
如果需要所有查询结果的_id默认就是字符串格式,可以在定义Schema时配置转换规则,查询时搭配lean()选项跳过Mongoose文档实例化,直接返回普通JS对象:
// 定义User Schema时添加全局转换配置 const userSchema = new Schema( { // 你的业务字段定义,比如username、age等 }, { toObject: { transform: (_, ret) => { ret._id = ret._id.toString(); return ret; } }, toJSON: { transform: (_, ret) => { ret._id = ret._id.toString(); return ret; } } } ); // 查询时加lean(),返回的普通对象中_id已经自动转为字符串 async findById(id: string) { const userDoc = await userModel.findById(id).lean(); // 此处userDoc._id已经是纯字符串,不需要额外转换 return userDoc; }
TypeScript类型提示:如果使用全局转换+lean的方案,定义用户文档类型时直接将
_id字段类型标注为string即可,避免类型校验报错。
内容的提问来源于stack exchange,提问作者Ali Corrales
相关产品推荐
相关产品推荐

