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

如何用Sequelize实现排行榜用户去重,避免同一用户重复显示?

解决排行榜重复显示同一用户的问题

你需要实现每个用户仅展示其最高分数的排行榜,下面提供两种可行方案:

方案一:在Sequelize查询层面直接获取用户最高分(推荐)

通过聚合查询+分组,直接从数据库拿到每个用户的最高分数,避免后续冗余数据处理:

首先确保你已引入Sequelize实例(比如从项目模型文件中导出),然后修改查询代码:

const sequelize = require('../models').sequelize; // 根据你的项目路径调整

router.get('/leaderboard', async (req, res) => {
    try {
        const scoreDataRaw = await Score.findAll({
            attributes: [
                [sequelize.fn('MAX', sequelize.col('score')), 'topScore'],
                'userId'
            ],
            include: [
                {
                    model: User,
                    attributes: ['username']
                }
            ],
            group: ['userId', 'User.id'], // 按用户ID分组,需包含关联模型ID避免分组报错
            order: [
                [sequelize.fn('MAX', sequelize.col('score')), 'DESC'] // 按最高分降序,符合排行榜逻辑
            ]
        });

        const scoreData = scoreDataRaw.map((score) => score.get({ plain: true }));
        // 注意此时每条数据的分数字段为topScore,模板渲染时需对应调整
        res.render('leaderboard', { scoreData });
    } catch (error) {
        res.status(500).json(error);
    }
});

注意:原代码中order: [['score', 'ASC']]是按分数升序(从低到高),和你注释的“descending”(降序)不符,方案中已修正为降序逻辑。

方案二:在JavaScript层面过滤重复用户

如果不想修改数据库查询逻辑,可以在拿到全量分数数据后,通过JS筛选每个用户的最高分条目:

router.get('/leaderboard', async (req, res) => {
    try {
        const scoreDataRaw = await Score.findAll({
            include: [
                {
                    model: User,
                    attributes: ['username']
                }
            ],
            order: [
                ['score', 'DESC'] // 先按分数降序,方便后续筛选
            ]
        });

        const scoreData = scoreDataRaw.map((score) => score.get({ plain: true }));

        // 过滤每个用户仅保留最高分的条目
        const userScoreMap = {};
        scoreData.forEach(item => {
            const userId = item.userId;
            if (!userScoreMap[userId] || item.score > userScoreMap[userId].score) {
                userScoreMap[userId] = item;
            }
        });
        // 转换为数组并保持分数降序排列
        const filteredScoreData = Object.values(userScoreMap).sort((a, b) => b.score - a.score);

        res.render('leaderboard', { scoreData: filteredScoreData });
    } catch (error) {
        res.status(500).json(error);
    }
});

两种方案对比:方案一通过数据库聚合查询,性能更优(尤其数据量大时);方案二无需调整查询逻辑,适合快速迭代场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 22:53:15