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

开发Discord Bot时遭遇MongoDB的BSONError循环依赖问题求助

BSONError: cyclic dependency detected(MongoDB原生驱动场景)

问题场景

开发Discord Bot过程中,使用MongoDB原生驱动操作数据库时,突然抛出BSONError: cyclic dependency detected错误。搜索发现现有公开解决方案大多针对Mongoose框架,针对原生驱动的排查思路极少,多方调试仍无法定位根因。

核心代码

业务逻辑代码片段

async start (recall: boolean = false) {
        console.log('Starting server...');
        if (recall && !this.started) {
            // ...
        } else if (this.started) {
            // ...
            } else if (!this.database) {
            // ...
            } else {
                let { connections } = this;
                connections = connections.map((connection: any) => {
                    const userStyle = parseInt(connection?.user?.style) || 0;
                    const userXp = parseInt(connection?.user?.xp) || 0;
                    const userPrevWars = Math.max(parseInt(connection?.user?.prevWars.length) || 0, 1);
                    const userLevel = XPtoLevel(userXp);


                    const parser = LeveltoXP(userXp);
                    const Rate = [Math.pow(userPrevWars, 1.125),Math.pow(userStyle, 0.875)];
                    const userPower = Math.max(
                        (Math.sqrt(100 + 8 * userXp) * Rate[0] * userStyle * (parser + userXp)) / 26 * parser * Rate[1],
                        1
                    );

                    return {
                        ...connection,
                        user: {
                            ...connection.user,
                            power: userPower
                        }
                    };
                });
                const avarage = connections.reduce((a,b) => a + (b?.user.power || 0)) / connections.length;
                const pointerPower = avarage * Math.random() / 2 + avarage / 2;
                
                connections?.forEach(async (connection: any, index: number) => {
                    const current = connection.user.power;
                    const enemy = connections[([1,0])[index]].user.power;
                    const chance = current / (current + enemy);
                    const win = pointerPower < current;

                    connection?.message?.reply('The match is starting! Please wait...');
                    setTimeout(() => {
                        
                        connection?.message?.reply(`Your power is ${current}, enemy power is ${enemy}. \n Your chance to win is ${Math.round(chance * 10) * 10}%`);
                        setTimeout(async () => {
                            connection?.message?.reply(`You ${win ? 'win' : 'lost'} the match!`);
                            
                            connection.user.xp += Math.max(
                                10,
                                Math.floor(Math.round(
                                    Math.abs(current - enemy) * enemy / current * (win ? 1 : 0.5)
                                ) * 100) / 100
                            );
                            connection.user.prevWars.push({
                                user: connection.user,
                                result: 'win',
                                time: new Date().getTime(),
                                xp: connection.user.xp,
                                enemy
                            });
                            console.log(connection.user);
                            await this.database.updateOne({ id: connection.user.id }, { $set: { xp: connection.user.xp, prevWars: connection.user.prevWars } });

                            this.removeConnection(connection);
                        }, 3000);
                    }, 1000)
                });
            }
        } else {
            ...
        }
    }

MongoDB原生驱动连接代码(mongo.ts)

import { MongoClient } from "mongodb";

class Database {
    constructor (url: any, dbName: any) {
        this.url = url;
        this.mongo = new MongoClient(url);
        this.database = null;
        this.databaseConnection = null;
        this.dbName = dbName;

        this.connect();
    }

    async connect() {
        this.database = await this.mongo.connect();
        this.databaseConnection = this.database.db(this.dbName);
        console.log(`Connected to ${this.dbName}`);
    }

    async disconnect() {
        await this.mongo.close();
    }

    async getCollection(name: string) {
        const collection = this.databaseConnection.collection(name);
        return collection;
    }
    
    url: any;
    mongo: any;
    database: any;
    databaseConnection: any;
    dbName: any;
}

export default Database;

报错信息

super(message);
    ^
BSONError: cyclic dependency detected
    at new BSONError (C:\Users\...\node_modules\bson\src\error.ts:4:5)
    at serializeObject (C:\Users\...\node_modules\bson\src\parser\serializer.ts:373:34)
    at serializeInto (C:\Users\...\node_modules\bson\src\parser\serializer.ts:1013:17)
    at serializeObject (C:\Users\...\node_modules\bson\src\parser\serializer.ts:387:20)
    at serializeInto (C:\Users\...\node_modules\bson\src\parser\serializer.ts:1013:17)
    at serializeObject (C:\Users\...\node_modules\bson\src\parser\serializer.ts:387:20)
    at serializeInto (C:\Users\...\node_modules\bson\src\parser\serializer.ts:802:17)
    at serializeObject (C:\Users\...\node_modules\bson\src\parser\serializer.ts:387:20)
    at serializeInto (C:\Users\...\node_modules\bson\src\parser\serializer.ts:1013:17)
    at serializeObject (C:\Users\...\node_modules\bson\src\parser\serializer.ts:387:20)

解决方法

放弃MongoDB原生驱动,改用mongoose框架替代,错误直接消失,同时Mongoose的封装特性也提升了开发效率。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 08:01:42