Mongoose v6.8.0中ID重复问题求助
Mongoose v6.8.0中Virtuals相关ID重复问题解决
问题描述
我在Mongoose中创建了包含virtuals的Schema,出现了ID重复的情况。查阅官方文档及旧代码,但这些方案均不适用于v6.8.0版本。以下是我的Tour Schema代码,MongoDB中的对象存在_id与id值重复的问题。
原Tour Schema代码
/** * Import only the mongoose in this class * This plugin is for MongoDB and this class decide how the Mongo document should be for the Tour objects */ import mongoose from 'mongoose'; import slugify from 'slugify'; /** * Config the Tour object what name and the type of attributes */ const tourSchema = new mongoose.Schema([ { name: { type: String, required: [true, 'A tour must have a name'], unique: true, trim: true, }, slug: String, duration: { type: Number, required: [true, 'A tour must have a duration'], }, maxGroupSize: { type: Number, required: [true, 'A tour must have a max group size'], }, difficulty: { type: String, required: [true, 'A tour must have a difficulty'], }, ratingsAverage: { type: Number, default: 4.5, }, ratingsQuantity: { type: Number, default: 0, }, price: { type: Number, required: [true, 'A tour must have a price'], }, priceDiscount: Number, summary: { type: String, trim: true, required: [true, 'A tour must have a summary'], }, description: { type: String, trim: true, }, imageCover: { type: String, trim: true, required: [true, 'A tour must have an cover image'], }, images: [String], createAt: { type: Date, default: Date.now, select: false, }, startDates: [Date], }, ]); tourSchema.set('toJSON', { getters: true, virtuals: true}); tourSchema.set('toObject', { getters: true, virtuals: true }); tourSchema.virtual('durationWeeks').get(function () { return this.duration / 7; }); // tourSchema.pre('save', function (next) { // this.slug = slugify(this.name, { lower: true }); // next(); // }); // tourSchema.post('save', function(doc,next){ // console.log(doc); // next(); // }); /** * Create a mogoose module this puts in the name and type of attributes Tour object should have and what must be writend and what is optional */ const Tour = mongoose.model('Tours', tourSchema); /** * Export the Tour constant */ export default Tour;
解决方案
核心问题定位
创建Schema时错误地将字段定义对象包裹在了数组中(new mongoose.Schema([{ ... }])),这会让Mongoose将其解析为Schema数组类型,而非单个文档的Schema结构。这种错误写法会干扰Mongoose默认的ID处理逻辑,再配合开启virtuals: true的配置,就会导致返回结果中同时出现原生_id和虚拟id字段,形成重复。
修复步骤
- 修正Schema创建方式:去掉外层数组,直接传入字段定义对象:
const tourSchema = new mongoose.Schema({ name: { type: String, required: [true, 'A tour must have a name'], unique: true, trim: true, }, // 其余字段定义保持不变... }); - (可选)优化ID返回格式:如果需要统一ID字段展示,可以通过
transform函数自定义返回结构,例如只保留id并移除_id:tourSchema.set('toJSON', { getters: true, virtuals: true, transform: function(doc, ret) { ret.id = ret._id.toString(); delete ret._id; delete ret.__v; // 可选:移除MongoDB默认的版本号字段 } }); tourSchema.set('toObject', { getters: true, virtuals: true, transform: function(doc, ret) { ret.id = ret._id.toString(); delete ret._id; delete ret.__v; } });
验证
修复后重新创建或更新文档,MongoDB中只会存储原生的_id字段,返回的JSON/Object结构中不会再出现ID重复的情况,同时虚拟字段durationWeeks仍能正常工作。
内容的提问来源于stack exchange,提问作者Tor Bloodaxe
相关产品推荐
相关产品推荐

