如何通过Sequelize从Sqlite数据库获取排行榜格式的数据?
问题:Discord.js + Sequelize 生成排行榜返回空消息
尝试通过Sequelize从SQLite数据库拉取用户与catches数据,在Discord消息中展示按catches数量排行的前10名,但返回的是空消息。
数据库模型定义
const Tags = sequelize.define('tags', { user: { type: Sequelize.STRING, unique: true, }, catches: { type: Sequelize.INTEGER, defaultValue: 0, allowNull: false, }, });
错误代码
if (commandName === 'leaderboard') { let board = Tags.findAll({ limit: 10, attributes: ['user', 'catches']}); lead = [] lead.push(board) console.log(lead) await interaction.reply( codeBlock( lead.sort((a, b) => b.balance - a.balance) .filter(user => client.users.cache.has(user.user_id)) .map((user, position) => `(${position + 1}) ${(user.tag)}: ${user.balance}`) .join("\n"), ), ); }
问题分析与修复
核心错误点
- 未处理异步操作:
Tags.findAll()返回Promise对象,直接赋值给board不会得到实际数据,必须用await等待Promise解析。 - 错误的数据结构:把Promise对象推入
lead数组,导致后续操作都是对无效对象执行,自然没有结果。 - 字段名不匹配:模型中存储数量的字段是
catches,但代码里错误使用了balance;用户ID字段是user,代码里写成了user_id。 - 排序逻辑错误:应该在数据库查询阶段就按
catches降序排序,确保拉取的是前10名的高数据,而不是拉取后再排序(且原排序字段错误)。 - 用户信息获取错误:模型中存储的是用户ID(
user字段),需要通过client.users.cache.get()获取用户对象才能拿到tag。
修正后的代码
if (commandName === 'leaderboard') { // 1. 等待数据库查询完成,同时按catches降序排序,取前10 const board = await Tags.findAll({ limit: 10, attributes: ['user', 'catches'], order: [['catches', 'DESC']] // 关键:数据库层面排序 }); // 2. 处理数据,生成排行榜内容 const leaderboardContent = board .map(entry => ({ userId: entry.user, catches: entry.catches })) // 过滤缓存中存在的用户 .filter(item => client.users.cache.has(item.userId)) // 生成排行文本 .map((item, index) => { const user = client.users.cache.get(item.userId); return `(${index + 1}) ${user.tag}: ${item.catches}`; }) .join('\n'); // 3. 回复消息,处理空数据情况 await interaction.reply( codeBlock(leaderboardContent || '暂无排行数据') ); }
额外说明
- 如果用户ID可能不在缓存中,可以考虑用
client.users.fetch(item.userId)获取(注意这也是异步操作,需要用Promise.all处理)。 - 始终用
await处理Sequelize的异步查询方法,避免操作Promise对象而非实际数据。
内容的提问来源于stack exchange,提问作者parker
相关产品推荐
相关产品推荐

