MongoDB使用mongoose时upsert:true插入结果不符合预期如何解决?
问题根因
- 更新参数语法错误:你在更新体中把
playerStatsObjForDB外层套了一层大括号,等价于{ playerStatsObjForDB: playerStatsObjForDB },实际是尝试写入一个名为playerStatsObjForDB的嵌套字段,而非将该对象内的playerName、points等字段写入文档根层级。由于你的Schema未定义该嵌套字段,Mongoose会默认忽略未声明字段,最终插入的文档仅保留查询条件里的_id和默认生成的__v字段。 - 若语法正确但仍缺失字段,需检查Points对应的Schema是否声明了
playerName、points字段,Mongoose默认不会插入Schema中未定义的字段。
解决方案
方案1:使用$set操作符更新字段(推荐,仅覆盖传入的字段,保留其他已有字段)
await Points.findOneAndUpdate( { "_id": playerStatsObjForDB._id }, // 直接传入对象给$set,会将对象内所有字段写入文档根层级 { $set: playerStatsObjForDB }, { upsert: true, new: true // 可选配置,开启后返回更新/插入后的最新文档 } );
方案2:开启overwrite全量替换文档(适合需要完全覆盖旧文档所有字段的场景)
await Points.findOneAndUpdate( { "_id": playerStatsObjForDB._id }, // 直接传完整文档对象,不要额外套外层大括号 playerStatsObjForDB, { upsert: true, overwrite: true, // 开启全量替换模式 new: true } );
Schema校验
确认你的Points模型的Schema定义包含所有需要写入的字段,示例如下:
const mongoose = require('mongoose'); const pointsSchema = new mongoose.Schema({ _id: { playerId: String, tournamentId: String, matchId: String }, playerName: String, points: Number }); const Points = mongoose.model('Points', pointsSchema);
内容的提问来源于stack exchange,提问作者Muhammad Danyal
相关产品推荐
相关产品推荐

