ExpressJS中Mongoose Populate返回多余字段问题求助
问题根源
- Tour Schema中的两个
pre(/^find/)中间件是全局触发的——只要查询Tour(包括被Review关联查询的场景),就会自动populateguides和leadGuide,所以你在Review的populate配置里设置select排除这些字段无效,中间件会再次添加这些关联数据。 - 多余的
id字段是Mongoose默认生成的虚拟字段,加上原生的_id导致重复;durationWeeks是Tour定义的虚拟字段,也会被返回。
解决步骤
1. 阻止Tour中间件在Review关联查询时执行
修改Tour Schema的两个pre(/^find/)中间件,添加判断逻辑,只有当不是从Review关联查询时才执行populate:
// 修改Tour的guides populate中间件 toursSchema.pre(/^find/, function (next) { // 若查询带有skipTourPopulate标志,跳过populate操作 if (this.options.skipTourPopulate) return next(); this.populate({ path: "guides", select: "-__v -passwordChangedAt -_id", }); next(); }); // 修改Tour的leadGuide populate中间件 toursSchema.pre(/^find/, function (next) { if (this.options.skipTourPopulate) return next(); this.populate({ path: "leadGuide", select: "-__v -passwordChangedAt -_id", }); next(); });
然后修改Review Schema中的tour populate配置,添加skipTourPopulate标志,同时指定只返回需要的字段:
reviewSchema.pre(/^find/, function (next) { this.populate({ path: "tour", select: "name _id", // 仅保留name和_id options: { skipTourPopulate: true } // 触发Tour中间件的跳过逻辑 }); next(); });
2. 移除多余的id字段
通过Schema的transform函数,在数据转换为JSON时删除不需要的字段:
处理Review的多余字段
修改Review Schema的配置:
const reviewSchema = new mongoose.Schema( { // ... 原有字段 }, { toJSON: { virtuals: true, versionKey: false, transform: function(doc, ret) { delete ret._id; // 删除原生_id delete ret.id; // 删除Mongoose生成的虚拟id } }, toObject: { virtuals: true }, id: false // 关闭自动生成虚拟id的功能 } );
处理Tour的多余字段
修改Tour Schema的配置:
const toursSchema = new mongoose.Schema( { // ... 原有字段 }, { timestamps: true, toJSON: { virtuals: true, transform: function(doc, ret) { delete ret.id; // 删除虚拟id delete ret.durationWeeks; // 若不需要该虚拟字段可一并删除 } }, toObject: { virtuals: true }, } );
最终效果
修改后查询Review返回的响应会变成:
"reviews": [ { "review": "This is a very nice tour.", "rating": 5, "createdAt": "2024-04-09T00:20:58.278Z", "tour": { "_id": "66147210f4db8c1f54af0e6f", "name": "Royal Bengal Tiger Safari" } } ]
内容的提问来源于stack exchange,提问作者Sp3cTer
相关产品推荐
相关产品推荐

