Nodejs中如何在count的同时进行sort来获取排名呢?

Nodejs中如何在count的同时进行sort来获取排名呢?

用户排名的话 在查询条件后,有相同条件的用户,对用户再进行一次排序(根据注册时间),来获取最后排序的结果

如: UserSchema = new Schema({ score: Number, joinTime: Date })

整体排名列表可以实现 但是如何获取用户的准确单独排名呢?

User.count({score : { $gte: user_score}}) 只有获得对分数的排名~

2 回复

Nodejs中如何在count的同时进行sort来获取排名呢?

在Node.js中,如果你想要在一个集合中同时进行计数和排序,并且获取每个用户的准确排名,你可以使用MongoDB的聚合框架来完成这个任务。假设我们有一个UserSchema,它包含用户的分数和加入时间,我们可以通过以下步骤来实现:

示例代码

const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
    score: Number,
    joinTime: Date
});

const User = mongoose.model('User', UserSchema);

async function getUserRank(user) {
    // 第一步:找到所有分数大于等于当前用户分数的用户数量
    const countQuery = await User.countDocuments({
        score: { $gte: user.score }
    });

    // 第二步:获取所有用户的分数和加入时间,并按分数降序、加入时间升序排序
    const rankList = await User.aggregate([
        {
            $match: {
                score: { $gte: user.score }
            }
        },
        {
            $sort: {
                score: -1, // 按分数降序排列
                joinTime: 1 // 如果分数相同,则按加入时间升序排列
            }
        },
        {
            $group: {
                _id: null,
                ranks: {
                    $push: {
                        userId: '$_id',
                        score: '$score',
                        joinTime: '$joinTime',
                        rank: { $indexOfArray: [ [ '$score' ], '$score' ] } + 1
                    }
                }
            }
        }
    ]);

    // 获取用户的排名
    let userRank = 0;
    if (rankList.length > 0) {
        const userIndex = rankList[0].ranks.findIndex(u => u.userId.equals(user._id));
        if (userIndex !== -1) {
            userRank = rankList[0].ranks[userIndex].rank;
        }
    }

    return {
        totalUsersWithHigherScore: countQuery,
        userRank: userRank
    };
}

// 使用示例
getUserRank({ score: 100, joinTime: new Date() }).then(result => {
    console.log(`用户排名:${result.userRank}`);
    console.log(`总共有${result.totalUsersWithHigherScore}个用户分数高于或等于该用户`);
});

解释

  1. 计算排名:我们首先通过countDocuments方法计算出分数大于等于当前用户分数的所有用户的数量。
  2. 排序和分组:然后我们使用aggregate方法来获取所有符合条件的用户,并按分数降序排列,如果分数相同,则按加入时间升序排列。通过$indexOfArray操作符来计算每个用户的排名。
  3. 查找用户排名:最后,我们在结果数组中找到当前用户的排名。

这种方法确保了我们不仅能获取到用户的排名,还能同时得到用户在分数上的总体排名情况。


要获取用户的准确排名并同时按某个字段排序(例如注册时间),你可以使用MongoDB的聚合框架。以下是一个示例代码,展示了如何在计数排名的同时进行排序。

假设我们有一个用户集合users,每个用户有一个score字段和一个joinTime字段。

const User = mongoose.model('User', UserSchema);

async function getUserRank(user) {
    const userScore = user.score;
    const userJoinTime = user.joinTime;

    // 聚合查询
    const result = await User.aggregate([
        {
            $match: { score: { $gte: userScore } }
        },
        {
            $sort: { score: -1, joinTime: 1 }  // 先按score降序,再按joinTime升序
        },
        {
            $group: {
                _id: null,
                rank: { $sum: 1 },
                highestScore: { $first: "$score" }
            }
        },
        {
            $project: {
                rank: 1,
                highestScore: 1,
                userRank: { $cond: [{ $eq: ["$$ROOT.highestScore", userScore] }, "$rank", "-"] }
            }
        }
    ]);

    if (result.length > 0) {
        return result[0].userRank;
    } else {
        return "未找到符合条件的用户";
    }
}

// 示例调用
const user = { score: 100, joinTime: new Date() };
getUserRank(user).then(rank => console.log(`用户的排名是: ${rank}`));

解释:

  1. $match: 过滤出所有score大于等于当前用户score的文档。
  2. $sort: 按score降序排序,如果score相同,则按joinTime升序排序。
  3. $group: 计算符合条件的文档数量,并将第一个文档的score作为最高分。
  4. $project: 创建一个新的字段userRank,如果当前用户的score等于最高分,则返回排名,否则返回-

这样,你就可以得到用户的准确排名。

回到顶部