如何在QuickMongo中筛选数据使Discord排行榜仅显示当前服务器内用户名称
解决方案
问题原因
- 你之前写的
data.filter()不会修改原数组,执行后会返回新的过滤后数组,你没有接收这个返回值,过滤操作等于没有生效 message.guild.members.fetch()是异步操作,原代码没有等待该请求执行完成就往下处理排行榜数据,过滤逻辑还没跑完就已经生成了排行榜内容
修正后完整代码
const Discord = require('discord.js') module.exports.run = async (bot, message, args, db) => { let eco = await db.fetch(`eco_${message.author.id}`) if(eco !== 'START') return message.reply(`you/They have not yet started your economy journey.\n**Start it now by typing \`gg ecostart\`**`) const ic = '<:mythicalcoin:842637611150606356>' let data = await db.startsWith("mon_"); try { // 等待获取当前服务器所有成员 const guildMembers = await message.guild.members.fetch() // 提取当前服务器所有成员ID存入Set,方便快速判断 const memberIdSet = new Set(guildMembers.map(m => m.id)) // 过滤数据,仅保留当前服务器成员的记录 data = data.filter(item => { const userId = item.ID.split('_')[1] return memberIdSet.has(userId) }) } catch (e) { console.log('获取服务器成员失败:', e) return message.reply('加载排行榜失败,请稍后重试') } // 排序后取前20 let money = data.sort((a, b) => (b.data - a.data)) money.length = Math.min(money.length, 20) if (money.length === 0) { return message.reply('当前服务器暂无排行榜数据') } var finalLb = ""; for (var i in money) { const userId = money[i].ID.split('_')[1] const member = await message.guild.members.fetch(userId) const username = member ? member.user.username : "Unknown User#0000" finalLb += `${parseInt(i)+1}. ${username} : ${ic} \`${parseInt(money[i].data).toLocaleString()}\`\n`; } const embed = new Discord.MessageEmbed() .setAuthor(`Leaderboard`, message.guild.iconURL()) .setColor("PURPLE") .setDescription(finalLb) .setFooter(bot.user.tag, bot.user.displayAvatarURL()) .setTimestamp() message.channel.send(embed); } module.exports.help = { name:"rich", aliases: ["lb", "leaderboard"] }
核心修改说明
- 新增
await等待服务器成员获取完成,确保过滤逻辑执行时已经拿到了完整的成员列表 - 将成员ID存入
Set,过滤逻辑直接判断用户ID是否在当前服务器成员集合中,执行效率更高 - 过滤后直接替换原
data数组,确保后续排序和渲染的都是当前服务器的用户数据 - 优化用户信息获取逻辑,避免重复发起成员请求,同时新增了空数据判断,避免生成空白排行榜
内容的提问来源于stack exchange,提问作者GentleScreamer
相关产品推荐
相关产品推荐

