You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mongoose查询返回文档出现与_id相同的额外id字段问题求助

问题原因与解决办法

嘿,这个问题我之前开发Mongoose项目时也碰到过,其实原因很清晰——你开启了Mongoose虚拟属性的序列化功能,而那个额外的id字段正是Mongoose默认给每个Schema自动添加的虚拟属性。

为什么会出现这个id字段?

Mongoose默认会为所有文档生成一个名为id的虚拟属性,它的值就是MongoDB原生的_id字段转换为字符串后的结果(毕竟_id是ObjectId类型,有时候我们需要字符串格式的ID来方便使用)。

而你在定义Crop Schema的时候,设置了如下选项:

{ 
  toJSON: { virtuals: true }, 
  toObject: { virtuals: true }, 
}

这就意味着当Mongoose把文档序列化成JSON(比如你用res.send(crops)返回给前端)或者普通JavaScript对象时,所有虚拟属性都会被包含进去,所以就出现了和_id值完全一致的id字段。

解决办法(三种可选方案)

根据你的需求,你可以选下面任意一种方式来移除这个额外的id字段:

方案1:完全关闭虚拟属性序列化

如果你不需要任何虚拟属性出现在返回结果里,直接把Schema选项中的virtuals设为false即可:

const cropSchema = new mongoose.Schema({
  nameOfCrop:{ 
    type:String, 
    lowercase:true, 
    required:'Please enter the name of the crop', 
    trim:true 
  },
  imageOfCrop:String,
  soilType: String,
  waterNeeded:String,
  tagCrop:String,//forage, vegetable, oilseeds etc.
  pesticideForCrop:[{ 
    type:mongoose.Schema.Types.ObjectId, 
    ref:'Pesticide' 
  } ]
}, { 
  toJSON: { virtuals: false }, 
  toObject: { virtuals: false } 
});

方案2:保留其他虚拟属性,仅移除id

如果你自己定义了其他需要保留的虚拟属性,可以通过transform函数在序列化时删除id字段:

const cropSchema = new mongoose.Schema({
  // 你的字段定义...
}, { 
  toJSON: { 
    virtuals: true,
    transform: function(doc, ret) {
      delete ret.id; // 移除虚拟的id字段
      return ret;
    }
  }, 
  toObject: { 
    virtuals: true,
    transform: function(doc, ret) {
      delete ret.id;
      return ret;
    }
  } 
});

方案3:直接关闭默认的id虚拟属性

你也可以在Schema选项里直接禁用Mongoose默认的id虚拟属性,这样不管是否开启虚拟属性序列化,这个字段都不会出现:

const cropSchema = new mongoose.Schema({
  // 你的字段定义...
}, { 
  id: false, // 关闭默认的id虚拟属性
  toJSON: { virtuals: true }, 
  toObject: { virtuals: true } 
});

修改完成后重启你的服务,再用Postman查询,就能看到返回结果里只剩下原生的_id字段啦。

内容的提问来源于stack exchange,提问作者Parikshit Hooda

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:02:24