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

discord.js结合MongoDB实现消息计数时messageCount字段无法创建

消息计数功能数据库写入失败问题排查

相关代码

message-counter.js

const mongo = require("mongoose")
const schema = require("./schemas/rank/message-count-schema")

module.exports = client => {
    
    client.on('messageCreate', async (message) => {    
        const { author } = message
        const { id } = author
        mongo.connect(
            process.env.MONGO_URI,
            { keepAlive: true }
        )

        const dataQuery = await schema.findOne({ _id: id })
        
        if (!dataQuery) {
            const newSchem = schema(
                {
                    _id: id
                },
                {
                    $setOnInsert: { messageCount: 1 }
                },
                {
                    $inc: { messageCount: 1 }
                },
                {
                    upsert: true
                }
            )
        
            await newSchem.save()
        }
        else {
            dataQuery.updateOne(
                {
                    $inc: { messageCount: 1 }
                },
                {
                    upsert: true
                }
            )
        }
    })
}

message-count-schema.js

const mongoose = require('mongoose');

const messageCountSchema = new mongoose.Schema({
    _id: {
        type: String,
        required: true
    },

    messageCount: {
        type: Number,
        required: true
    }
})

module.exports = mongoose.model('message-count', messageCountSchema);

运行效果参考

运行效果截图

错误点与修复方向

  • 数据库连接位置错误:mongo.connect()被写在messageCreate事件回调内部,每次收到消息都会重复发起连接,且没有await等待连接完成就执行后续查询写入,操作执行时连接大概率未就绪。修复方向:将MongoDB连接逻辑移到机器人初始化阶段,全局只连接一次,确认连接成功后再注册事件监听。
  • Mongoose模型实例化参数错误:给模型构造函数schema()传入了$setOnInsert、$inc、upsert这类更新操作符配置,模型构造函数仅接收文档字段键值对,不识别更新操作符,会导致新生成的文档实例仅包含_id字段,缺失必填的messageCount字段,save()操作会触发校验失败无法写入。修复方向:创建新文档时仅传入实际字段值,不要混入更新操作符;如果要实现upsert(不存在则创建、存在则更新)逻辑,直接调用模型的静态更新方法(如findOneAndUpdate),不要手动拆分「查询-判断-创建/更新」分支。
  • 更新操作缺少异步等待:已存在用户数据的分支中,调用dataQuery.updateOne()时没有加await,该方法返回的Promise没有被等待,更新逻辑会在执行完成前被终止,无法写入数据库。
  • 并发竞态风险:现有分两步的查询写入逻辑在高并发场景(短时间收到同一用户多条消息)下,会出现多次查询到数据不存在、重复创建文档的问题,可通过单条带upsert配置的原子更新语句替代现有分支逻辑解决。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 20:01:22