如何使用Mongoose实现多字段递增?解决重复创建条目问题
问题原因与修复方案
核心问题
- 用户ID大小写不匹配:在字符串选择菜单(
reason部分)的代码中,你在更新文档里写了userID: interaction.user.ID(大写ID),但查询条件用的是interaction.user.id(小写id)。Discord用户ID是大小写敏感的字符串,这就导致程序找不到已存在的用户条目,触发upsert: true创建新条目,而新条目的userID和之前的不匹配,最终重复创建。 - 冗余的
userID赋值:在findOneAndUpdate的更新参数里手动设置userID完全没必要——开启upsert: true时,Mongoose会自动把查询条件里的userID作为新文档的字段值,手动赋值反而可能引发逻辑冲突。
修复后的代码
修复accept/deny部分(去掉冗余的userID赋值)
if (interaction.customId === 'accept') { leaderboard.findOneAndUpdate( { userID: interaction.user.id }, { $inc: { accepts: 1 } }, // 移除多余的userID赋值 { upsert: true, new: true }, (err, doc) => { if (err) console.log(err); console.log(`Updated ${interaction.user.username}'s accepts to ${doc.accepts} `); } ); } if (interaction.customId === 'deny') { leaderboard.findOneAndUpdate( { userID: interaction.user.id }, { $inc: { denies: 1 } }, // 移除多余的userID赋值 { upsert: true, new: true }, (err, doc) => { if (err) console.log(err); console.log(`Updated ${interaction.user.username}'s denies to ${doc.denies} `); } ); }
修复reason选择菜单部分(修正ID大小写+移除冗余赋值)
if (interaction.isStringSelectMenu()) { if (interaction.customId === 'reason') { if (reason === 'nsfw') { leaderboard.findOneAndUpdate( { userID: interaction.user.id }, { $inc: { nsfw: 1 } }, // 移除userID赋值,修正了之前的ID大小写错误 { upsert: true, new: true }, (err, doc) => { if (err) console.log(err); console.log(`Updated ${interaction.user.username}'s ${reason} to ${doc.nsfw} `); } ); } if (reason === 'copyright') { leaderboard.findOneAndUpdate( { userID: interaction.user.id }, { $inc: { copyright: 1 } }, { upsert: true, new: true }, (err, doc) => { if (err) console.log(err); console.log(`Updated ${interaction.user.username}'s ${reason} to ${doc.copyright} `); } ); } if (reason === 'invalid_format') { leaderboard.findOneAndUpdate( { userID: interaction.user.id }, { $inc: { invalid_format: 1 } }, { upsert: true, new: true }, (err, doc) => { if (err) console.log(err); console.log(`Updated ${interaction.user.username}'s ${reason} to ${doc.invalid_format} `); } ); } } }
额外优化建议
如果你的项目允许,建议用async/await代替回调函数,代码可读性会更高,比如:
// 示例:accept按钮的async/await写法 if (interaction.customId === 'accept') { try { const doc = await leaderboard.findOneAndUpdate( { userID: interaction.user.id }, { $inc: { accepts: 1 } }, { upsert: true, new: true } ); console.log(`Updated ${interaction.user.username}'s accepts to ${doc.accepts} `); } catch (err) { console.log(err); } }
内容的提问来源于stack exchange,提问作者Jonathan Jones
相关产品推荐
相关产品推荐

