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

C#操作MongoDB查询考生成绩时如何获取其按总分排序的排名

解决方案

实现思路

  • 首先需要先在ExamCandidateResult实体类中新增Rank属性,用于接收计算得到的排名值
  • 采用MongoDB聚合管道实现排名计算:先过滤指定考试的全部考生、按总分降序排序、用窗口函数计算排名、最后匹配目标考生记录即可同时拿到成绩和排名

代码修改(适配MongoDB 5.0+版本,推荐)

MongoDB 5.0以上版本支持$setWindowFields窗口函数,可直接在数据库侧高效计算排名:

// 先给ExamCandidateResult类新增Rank属性
public class ExamCandidateResult
{
    // 原有其他属性保持不变
    public int Rank { get; set; }
}
public ExamCandidateResult ExaminationGetCandidateResultStatus(Guid examinationId, Guid candidateId)
{
    var con = new MongoClient(DBConnection.ExamConnectionString);
    var db = con.GetDatabase(ExamDB);
    var collection = db.GetCollection<ExamCandidateResult>("Examination");

    var examIdStr = examinationId.ToString();
    var candidateIdStr = candidateId.ToString();

    // 聚合管道计算排名
    var data = collection.Aggregate()
        // 第一步:过滤指定考试的所有考生
        .Match(Builders<ExamCandidateResult>.Filter.Eq("ExaminationID", examIdStr))
        // 第二步:按总分降序排序,同分可自定义排序规则,比如按交卷时间升序
        .SortByDescending(x => x.TotalMarks)
        // 第三步:窗口函数计算排名
        .AppendStage<ExamCandidateResult>(new BsonDocument("$setWindowFields",
            new BsonDocument
            {
                { "sortBy", new BsonDocument("TotalMarks", -1) },
                { "output", new BsonDocument("Rank", new BsonDocument("$rank", new BsonDocument())) }
            }))
        // 第四步:过滤出目标考生
        .Match(Builders<ExamCandidateResult>.Filter.Eq("CandidateID", candidateIdStr))
        .FirstOrDefault();

    // 若需要使用同分连续排名,把上面的$rank替换为$denseRank即可
    return data;
}

低版本MongoDB兼容方案(<5.0版本)

如果你的MongoDB版本不支持窗口函数,可以用两次查询的方式实现:

public ExamCandidateResult ExaminationGetCandidateResultStatus(Guid examinationId, Guid candidateId)
{
    var con = new MongoClient(DBConnection.ExamConnectionString);
    var db = con.GetDatabase(ExamDB);
    var collection = db.GetCollection<ExamCandidateResult>("Examination");

    var examIdStr = examinationId.ToString();
    var candidateIdStr = candidateId.ToString();

    // 先查询目标考生的成绩
    var filter = Builders<ExamCandidateResult>.Filter.Eq("ExaminationID", examIdStr)
               & Builders<ExamCandidateResult>.Filter.Eq("CandidateID", candidateIdStr);
    var candidateData = collection.Find(filter).FirstOrDefault();
    if (candidateData == null) return null;

    // 统计同考试下总分高于当前考生的人数,+1就是当前考生的排名
    var higherScoreCountFilter = Builders<ExamCandidateResult>.Filter.Eq("ExaminationID", examIdStr)
                               & Builders<ExamCandidateResult>.Filter.Gt(x => x.TotalMarks, candidateData.TotalMarks);
    var higherCount = collection.CountDocuments(higherScoreCountFilter);
    candidateData.Rank = (int)higherCount + 1;

    // 若需要同分按其他维度排序,可在统计条件里额外加规则
    return candidateData;
}

注意事项

  • $rank规则:同分考生排名相同,后续排名会跳过重复位数,比如2个并列第1,下一名排名为3
  • $denseRank规则:同分考生排名相同,后续排名连续,比如2个并列第1,下一名排名为2
  • 低版本方案在考生数据量极大的场景下性能略低于窗口函数方案,有条件建议升级MongoDB到5.0以上版本

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 22:15:03