如何用Mongoose的.find()实现Discord机器人用户重复添加校验?
问题解决思路
核心问题分析
- 异步操作处理错误:Mongoose的
find方法返回的是Query对象,不是布尔值,直接用!ModeratorSchema.find(...)判断永远为true,导致每次都执行创建操作。而MongoDB因为user_id的唯一约束会拒绝重复插入,但你的代码没有捕获这个错误,所以Discord仍会返回“添加成功”的提示。 - 校验代码语法错误:你之前的校验代码把回调函数写在了括号外,语法错误导致代码不执行,自然没有输出;另外
find返回的是数组,即使无数据也是空数组[],用if (data)判断会认为空数组为真,逻辑错误。
修正后的代码实现
方法1:使用Async/Await(推荐)
将命令处理函数改为异步函数,先查询用户是否存在,再执行后续逻辑:
// 确保你的命令处理函数是async的 async function handleModeratorAdd(interaction) { const target = interaction.options.getUser('target'); // 假设你通过此获取目标用户 const permissionType = interaction.options.getInteger("type"); const log_channel = "你的日志频道ID"; try { // 查询数据库中是否存在该用户 const existingModerator = await ModeratorSchema.findOne({ user_id: target.id }); if (existingModerator) { return interaction.reply({ content: "User is already a system moderator.", ephemeral: true }); } // 创建新管理员记录 await ModeratorSchema.create({ username: target.username, user_id: target.id, type: permissionType }); // 发送成功反馈与日志 await interaction.reply({ content: `Added \`${target} (${target.id})\` as a system moderator with permission level ${permissionType}`, ephemeral: true }); await client.channels.cache.get(log_channel).send({ content: `\`${target} (${target.id})\` was added as a system moderator by \`${interaction.user.username} (${interaction.user.id})\` with permission level \`${permissionType}\`.` }); } catch (err) { // 捕获MongoDB唯一约束错误 if (err.code === 11000) { return interaction.reply({ content: "User is already a system moderator.", ephemeral: true }); } // 处理其他异常 console.error("Error adding moderator:", err); return interaction.reply({ content: "An error occurred while adding the moderator.", ephemeral: true }); } }
方法2:使用回调函数(兼容旧代码)
如果更习惯回调风格,修正语法与逻辑:
const target = interaction.options.getUser('target'); const permissionType = interaction.options.getInteger("type"); const log_channel = "你的日志频道ID"; ModeratorSchema.findOne({ user_id: target.id }, (err, existingModerator) => { if (err) { console.error("Error checking moderator:", err); return interaction.reply({ content: "An error occurred while checking moderator status.", ephemeral: true }); } if (existingModerator) { return interaction.reply({ content: "User is already a system moderator.", ephemeral: true }); } ModeratorSchema.create({ username: target.username, user_id: target.id, type: permissionType }, (createErr) => { if (createErr) { if (createErr.code === 11000) { return interaction.reply({ content: "User is already a system moderator.", ephemeral: true }); } console.error("Error creating moderator:", createErr); return interaction.reply({ content: "An error occurred while adding the moderator.", ephemeral: true }); } interaction.reply({ content: `Added \`${target} (${target.id})\` as a system moderator with permission level ${permissionType}`, ephemeral: true }); client.channels.cache.get(log_channel).send({ content: `\`${target} (${target.id})\` was added as a system moderator by \`${interaction.user.username} (${interaction.user.id})\` with permission level \`${permissionType}\`.` }); }); });
关键注意事项
- 使用
findOne而非find:find返回数组,即使无数据也是空数组;findOne找不到数据时返回null,判断更直接。 - 捕获唯一约束错误:即使提前查询,也可能因并发请求出现竞态条件,必须捕获MongoDB的
11000错误码,确保反馈准确。 - 等待异步操作完成:无论是
await还是回调,都要确保数据库操作完成后再执行Discord回复,避免逻辑混乱。
内容的提问来源于stack exchange,提问作者Aestriex
相关产品推荐
相关产品推荐

