MongoDB仅使用第一个条目

xsuvu9jc  于 2022-10-22  发布在  Go
关注(0)|答案(1)|浏览(209)

我做了一个冒险命令,在Mongo数据库中搜索个人资料,然后使用这些信息来计算XP、硬币等。我还使用了其他几个使用数据库的命令,这些命令工作得很好。然而,这个命令一开始很好地找到了正确的文档,但当我试图用调用的文档中的信息填充命令时,它只从数据库中属于我的个人资料的第一个文档中提取信息。所以,每次有人冒险时,它都会根据我的个人资料来计算一切,然后把它添加到正确的个人资料中。因此,他们继续赚取XP和硬币,而不是根据自己的个人资料信息。请参阅下面的代码。

const { SlashCommandBuilder } = require('@discordjs/builders');
const { Collection, MessageActionRow, MessageButton } = require("discord.js");
const econModel = require('../models/econModel');
const humanizeDuration = require('humanize-duration');
const adventureCooldowns = new Collection();

module.exports = {
    data: new SlashCommandBuilder()
        .setName("adventure")
        .setDescription("Explore the world and find treasure"),

    execute(interaction){
        const Member = interaction.member;
        const memberHasAdvCooldown = adventureCooldowns.has(Member.id);
        function getRandomInt(min, max) {
            min = Math.ceil(min);
            max = Math.floor(max);
            return Math.floor(Math.random() * (max - min)) + min;
        }

        if(memberHasAdvCooldown){
            const remaining1 = adventureCooldowns.get(Member.id) - new Date();
            const remainingFormatted1 = humanizeDuration(remaining1, {
                language: 'en',
                round: true,
                units: ['h', 'm', 's'],
            })
            interaction.reply({ content: `You must wait ${remainingFormatted1} for the cooldown period to end before adventuring again.`, ephemeral: true});
        }

        if(!adventureCooldowns.has(Member.id)){
            econModel.findOne({ MemberId: Member.id }, async (err, Account) => {
                if(err) throw err;
                if(Account) {
                    console.log(`ID: ${Member.id}\n${Member.nickname}`);
                    const curXp = Account.Exp;
                    console.log(`Current XP: ${curXp}`);
                    const curLvl = Account.Level;
                    console.log(`Curent Level: ${curLvl}`);
                    const coinBonus = Account.coinBonus;
                    console.log(`Coin Bonus: ${coinBonus}`);
                    const xpBonus = Account.expBonus;
                    console.log(`XP Bonus: ${xpBonus}`);
                    const xpBase = Math.floor(Math.random() * 10 + 50);
                    console.log(`Base XP: ${xpBase}`);
                    const xpLvlBonus = xpBase * curLvl;
                    console.log(`lvl XP: ${xpLvlBonus}`);
                    const xpTotal = Math.floor(xpLvlBonus * xpBonus);
                    console.log(`Total: ${xpTotal}`);
                    const Coins = getRandomInt(25, 200);
                    console.log(`Base coins: ${Coins}`);
                    const coinAdd = Math.floor(Coins * coinBonus);
                    console.log(`total coins: ${coinAdd}`);
                    const nextLvl = (500 * Math.pow(2, curLvl))/2;
                    console.log(`Next level: ${nextLvl}`);
                    const newExp = curXp + xpTotal;
                    if(nextLvl <= newExp){
                        econModel.collection.updateOne({ MemberID: Member.id }, { $inc: {Level: +1} });
                        econModel.collection.updateOne({ MemberID: Member.id }, { $inc: {Fowlercoins: +coinAdd} });
                        econModel.collection.updateOne({ MemberID: Member.id }, { $inc: {Exp: +xpTotal} });
                        interaction.reply({ content: `${Member.nickname}\nYou have leveled up! You are now level ${Account.Level + 1}!\nYou gained ${xpTotal} experience and found ${coinAdd} coins.`, components: [] });                        
                        econModel.collection.updateOne({ MemberID: Member.id }, { $set: {Next: nextLvl} });
                        adventureCooldowns.set(Member.id, Date.now() + 5000); //5000 is 5 seconds
                        setTimeout(() => adventureCooldowns.delete(Member.id), 5000);
                    } else{
                        econModel.collection.updateOne({ MemberID: Member.id }, { $inc: {Fowlercoins: +coinAdd} });
                        econModel.collection.updateOne({ MemberID: Member.id }, { $inc: {Exp: +xpTotal} });
                        interaction.reply({ content: `${Member.nickname}\nYou gained ${xpTotal} experience and found ${coinAdd} coins.`, components: [] })                        
                        econModel.collection.updateOne({ MemberID: Member.id }, { $set: {Next: nextLvl} });
                        adventureCooldowns.set(Member.id, Date.now() + 5000); //5000 is 5 seconds
                        setTimeout(() => adventureCooldowns.delete(Member.id), 5000);
                    }
                } else{
                    interaction.reply({ embeds: [new MessageEmbed()
                        .setTitle("ECONOMY SYSTEM")
                        .setColor("#3be820")
                        .setDescription(`${interaction.member.nickname} does not have an account! To create one, use /economy start!`)
                        .setFooter({ text: 'Rum Bot 1.4.5' })]});
                }
            })
        }
    }
}

如您所见,它尝试使用的第一件事是被调用文档中的Account.Exp,但它总是用数据库中的第一个文档填充它。你知道怎么阻止这件事发生吗?我已经努力了一个星期,但还没有取得任何进展。

z31licg0

z31licg01#

评论中来自测试的其他信息非常有用,信息量也很大。
听起来,您系统中的实际数据并不是您期望的那样。因此,系统可能运行正常,而意外行为是当前数据的结果。按顺序浏览部分评论将有助于回答这个问题。
我使用了.count方法和.findOne()方法。计票员带回了10份文件,尽管告诉它要找到具有特定ID的那一份
这里的“尽管告诉它要找到具有特定ID的那个文档*”的措辞很有趣。MemberId字段的econModel集合中是否有unique index?如果不是,则数据库本身不存在强制执行隐含声明的约束,即应该只有一个文档的MemberId字段具有给定值。
不过,findOne查询的行为有所不同。尽管请求特定的文档(不是集合中的第一个文档),它仍然会返回第一个文档。FindOne查询似乎未正确运行。
为什么你认为findOne({MemberId: <val>})的输出是错误的?返回的文档的MemberId字段的值是否与您查询的值不同?
根据您的测试,我的印象是您的econModel集合中有10文档,它们的MemberId字段的值与您正在搜索的文档相匹配。在接下来的步骤中,我建议检查所有这些值((.find({MemberId: <val>})),如果它们不是预期的值,则更新值,如果希望数据库在该字段上强制执行唯一性,则在该字段上创建唯一索引。可能还需要仔细检查代码中是否存在最初导致差异的错误(与手动测试相反)。

相关问题