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

discord.py警告系统MongoDB数据更新异常:无法追加警告对象而是替换原对象

解决Discord.py警告系统MongoDB追加数据问题

我来帮你搞定这个警告系统的问题!你的核心问题是没有正确判断用户是否已有警告记录,而且在更新时误用了操作符和变量,导致每次都覆盖而不是追加。咱们一步步修改:

原代码的核心问题

  • first_warning变量初始化后始终为True,没有根据数据库查询结果动态更新,导致每次都执行upsert覆盖原有数据
  • 查询用户记录后没有校验是否存在,直接默认是首次警告
  • 更新操作中键名不匹配(原数据用warn数组,你写成了warns),查询条件错误地把user.id当成字符串而非变量
  • 使用$push时逻辑错误,不需要先取数组再append,MongoDB的$push可以直接追加单个对象

修改后的完整代码

@commands.command()
@commands.guild_only()
# @commands.has_guild_permissions(kick_members=True)
async def warn(self, ctx, user: discord.User, *, reason=None):
    if user is None:
        await ctx.send("You have not provided a user!")
        return
    if user.bot:
        await ctx.send(f"<@{ctx.author.id}>, you cannot warn a bot!")
        return
    if user.id == ctx.author.id:
        embed = discord.Embed(description=f"<@{ctx.author.id}>, you are not allowed to warn yourself!")
        embed.set_author(name=ctx.author.display_name, icon_url=ctx.author.avatar_url)
        embed.set_footer(text=f"{ctx.message.guild.name} Custom Designed Bot")
        embed.timestamp = ctx.message.created_at
        await ctx.send(embed=embed)
        return
    
    # 处理默认原因
    reason = reason or "No reason provided"
    
    # 查询用户是否已有警告记录
    existing_warns = await self.bot.warns.find_by_id({"_id": user.id})
    
    # 构造新的警告对象
    new_warn_entry = {
        "PunishType": 'warn',
        "Moderator": ctx.author.id,
        "Reason": reason,
        "Timestamp": ctx.message.created_at  # 建议加上时间戳,方便后续查看
    }
    
    if not existing_warns:
        # 首次警告,插入新文档
        warn_doc = {
            "_id": user.id,
            "guild": ctx.guild.id,
            "warn": [new_warn_entry]
        }
        await self.bot.warns.upsert(warn_doc)
        embed_desc = f"<@{ctx.author.id}> has warned <@{user.id}> for: {reason}"
    else:
        # 已有警告,追加新的警告到数组
        await self.bot.warns.update(
            {"_id": user.id},
            {"$push": {"warn": new_warn_entry}}  # 使用$push直接追加单个对象
        )
        embed_desc = f"<@{ctx.author.id}> has added another warning to <@{user.id}> for: {reason}"
    
    # 发送成功提示Embed
    embed = discord.Embed(description=embed_desc)
    embed.set_author(name=ctx.author.display_name, icon_url=ctx.author.avatar_url)
    embed.timestamp = ctx.message.created_at
    await ctx.send(embed=embed)

关键修改点说明

  1. 动态判断首次警告:通过existing_warns = await self.bot.warns.find_by_id({"_id": user.id})查询数据库,根据返回结果判断是否为首次警告
  2. 修正$push用法:直接使用{"$push": {"warn": new_warn_entry}}让MongoDB自动把新警告对象追加到warn数组末尾,不需要手动操作数组
  3. 修复变量和键名错误:把查询条件里的"user.id"改成user.id(去掉引号,使用变量值),统一数组键名为warn
  4. 新增时间戳:给每个警告对象加上Timestamp字段,方便后续查看警告时间
  5. 优化提示内容:根据是否首次警告,发送不同的提示信息

这样修改后,每次执行警告命令时,系统会自动判断用户是否已有警告记录,首次则插入新文档,非首次则追加新的警告对象到数组中,不会再覆盖原有数据啦!

内容的提问来源于stack exchange,提问作者Jango DarkWind

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 04:47:28