You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用discord.js v14与Mongoose开发Discord机器人Warn命令时递增数值报错

问题描述

使用discord.js v14 + 最新版Mongoose开发Discord机器人警告命令,需求是:首次警告用户时number字段设为1,再次警告同一用户时该字段自增为2,但执行命令时触发验证错误。

错误信息

错误:Warn验证失败:number:在路径"number"处,将值"{ '$inc': 1 }"(类型为Object)转换为字符串失败
    at ValidationError.inspect (C:\Users\Robin\Documents\Multi-Purpose Bot\node_modules\mongoose\lib\error\validation.js:49:26)
    at formatValue (node:internal/util/inspect:782:19)
    at inspect (node:internal/util/inspect:347:10)
    at formatWithOptionsInternal (node:internal/util/inspect:2167:40)
    at formatWithOptions (node:internal/util/inspect:2029:10)
    at console.value (node:internal/console/constructor:332:14)
    at console.warn (node:internal/console/constructor:365:61)
    at C:\Users\Robin\Documents\Multi-Purpose Bot\Commands\Moderation\warn.js:60:40
    at C:\Users\Robin\Documents\Multi-Purpose Bot\node_modules\mongoose\lib\model.js:5195:18
    at processTicksAndRejections (node:internal/process/task_queues:78:11) {
  errors: {
    number: CastError: 在路径"number"处,将值"{ '$inc': 1 }"(类型为Object)转换为字符串失败
        at SchemaString.cast (C:\Users\Robin\Documents\Multi-Purpose Bot\node_modules\mongoose\lib\schema\string.js:603:11)
        at SchemaString.SchemaType.applySetters (C:\Users\Robin\Documents\Multi-Purpose Bot\node_modules\mongoose\lib\schematype.js:1201:12)
        at model.$set (C:\Users\Robin\Documents\Multi-Purpose Bot\node_modules\mongoose\lib\document.js:1368:22)
        at model.$set (C:\Users\Robin\Documents\Multi-Purpose Bot\node_modules\mongoose\lib\document.js:1093:16)
        at model.Document (C:\Users\Robin\Documents\Multi-Purpose Bot\node_modules\mongoose\lib\document.js:166:12)
        at model.Model (C:\Users\Robin\Documents\Multi-Purpose Bot\node_modules\mongoose\lib\model.js:121:12)
        at new model (C:\Users\Robin\Documents\Multi-Purpose Bot\node_modules\mongoose\lib\model.js:5020:15)
        at Object.execute (C:\Users\Robin\Documents\Multi-Purpose Bot\Commands\Moderation\warn.js:57:27)
        at Object.execute (C:\Users\Robin\Documents\Multi-Purpose Bot\Events\interactions\interactionCreate.js:12:21)
        at Client.<anonymous> (C:\Users\Robin\Documents\Multi-Purpose Bot\Handlers\eventHandler.js:25:63) {
      stringValue: `"{ '$inc': 1 }"`,
      messageFormat: undefined,
      kind: 'string',
      value: [Object],
      path: 'number',
      reason: null,
      valueType: 'Object'
    }
  },
  _message: 'Warn验证失败'
}

问题原因

  1. 错误使用$inc操作符:$inc是Mongoose的更新操作符,只能用于更新已有文档,不能直接在创建新文档时赋值给字段。你把它当成普通值传给number字段,导致Mongoose尝试把这个对象转换成字符串(因为Schema中number字段被定义为String类型),触发类型转换错误。
  2. 逻辑缺失:当前代码每次警告都创建新文档,没有实现“同一用户再次警告时递增number”的核心逻辑。

修复步骤

步骤1:修正Warn Schema结构

确保../../Models/Warn.js中number字段为Number类型(支持数值递增),示例Schema:

const mongoose = require('mongoose');

const WarnSchema = new mongoose.Schema({
    userId: { type: String, required: true },
    reason: { type: String, required: true },
    Date: { type: String, required: true },
    staffId: { type: String, required: true },
    number: { type: Number, required: true }
});

module.exports = mongoose.model('Warn', WarnSchema);

步骤2:重构命令逻辑

  • 先查询目标用户已有警告记录数,计算最新的number值
  • 首次警告时number设为1,后续警告设为已有记录数+1
  • 创建新警告文档并保存

修改后的完整命令代码

const { Client, SlashCommandBuilder, EmbedBuilder, PermissionFlagsBits } = require("discord.js");
const Schema = require("../../Models/Warn");

module.exports = {
    data: new SlashCommandBuilder()
        .setName("warn")
        .setDescription("Warns a member in your guild. **ADMIN**")
        .setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers)
        .addUserOption(option => 
            option.setName("target")
                .setDescription("Select the user you wish to warn.")
                .setRequired(true)
        )
        .addStringOption(option =>
            option.setName("reason")
                .setDescription("What is the reason of the warn?")
        ),

    async execute(interaction) {
        const { guild, options } = interaction;

        const user = options.getUser("target");
        const member = guild.members.cache.get(user.id);
        const reason = options.getString("reason") || "No reason provided";

        const errEmbed = new EmbedBuilder()
            .setDescription('Something went wrong. Please try again later.')
            .setColor(0xc72c3b);

        const successEmbed = new EmbedBuilder()
            .setTitle("**:white_check_mark: Warned**")
            .setDescription(`Successfully warned ${user}.`)
            .addFields(
                { name: "Reason", value: `${reason}`, inline: true }
            )
            .setColor(0x5fb041)
            .setTimestamp();

        // 权限检查
        if (member.roles.highest.position >= interaction.member.roles.highest.position)
            return interaction.reply({ embeds: [errEmbed], ephemeral: true });
            
        if(!interaction.guild.members.me.permissions.has(PermissionFlagsBits.ModerateMembers))
            return interaction.reply({ embeds: [errEmbed], ephemeral: true });

        try {
            // 格式化日期
            const date_ob = new Date();
            const date = date_ob.getDate();
            const month = date_ob.getMonth() + 1;
            const year = date_ob.getFullYear();
            const actualDate = `${year}-${month}-${date}`;

            // 查询用户已有警告数量,计算新的警告编号
            const existingWarns = await Schema.countDocuments({ userId: member.id });
            const newWarnNumber = existingWarns + 1;

            // 创建新警告文档
            const newWarn = new Schema({
                userId: member.id,
                reason: reason,
                Date: actualDate,
                staffId: interaction.member.user.username, // 修正原代码中获取管理员名称的错误
                number: newWarnNumber
            });

            await newWarn.save();
            console.log("New user has been warned. Saved to database.");

            interaction.reply({ embeds: [successEmbed], ephemeral: true });
        } catch (err) {
            console.error(err);
            return interaction.reply({ embeds: [errEmbed], ephemeral: true });
        }
    }
};

额外优化说明

  • 修正了原代码中interaction.member.name的错误,改用interaction.member.user.username获取管理员用户名
  • 简化日期格式化代码,直接使用Date对象处理
  • 添加await等待文档保存完成,避免异步逻辑问题
  • 在catch块中新增用户端错误反馈,提升交互体验

内容的提问来源于stack exchange,提问作者Bob Dylan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 16:50:33