You need to enable JavaScript to run this app. Mongoose配合TypeScript查询MongoDB返回_id格式异常问题
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 23:15:06