基于Firestore的学生考试评分及前25%排名查询方案咨询
不重构现有数据结构的实现思路
- 第一步:预加载指定科目标准答案
先一次性拉取answerkeys集合中所有对应科目的文档,缓存该科所有题目的正确答案、对应分值,避免评分过程中重复查询数据库。 - 第二步:一次性查询所有选考目标科目的学生
利用Firestore的OR逻辑查询条件,匹配subject1 == 目标科目、subject2 == 目标科目、subject3 == 目标科目三个条件,单次查询即可拉取所有符合条件的学生数据,无需分三次查询。提前为这三个字段建复合索引即可保证查询效率。 - 第三步:批量计算学生该科总分
遍历查询到的学生列表,逐一比对学生answer字段中对应科目的答题记录和预加载的标准答案,累加正确题目对应的分值,得到学生该科的总得分。 - 第四步:排序筛选前25%学生
将所有学生的该科得分按降序排序,取总人数前25%的条目即可。1000条数据的排序计算量极小,无论是在前端还是云函数侧执行都不会有性能压力。
*优化小技巧:可以将评分逻辑放在Firebase云函数中执行,计算完成后将各科总分直接写入对应用户文档的新增字段中,后续查询排名无需重复评分,直接拉取总分字段排序即可。
最优数据结构优化方案
如果后续可以调整数据结构,建议做以下修改进一步提升性能:
- 学生选科字段优化:将
subject1/subject2/subject3三个独立字段改为数组类型的selectedSubjects字段,后续查询选考某科的学生直接使用array-contains条件,查询逻辑更简洁,索引维护成本更低。 - 答题存储结构优化:将
answer字段按科目拆分二级结构,示例:
评分时无需过滤其他科目的答题记录,遍历效率更高。answer: { math: {"01":"a", "02":"b"}, science: {"01":"c", "02":"a"} } - 新增总分预存字段:在用户文档中新增
subjectScoresMap字段,考试提交后自动触发云函数计算所有选考科目的总分写入该字段,后续查询排名时直接按subjectScores.${目标科目}排序即可,无需重复执行评分逻辑。 - 高频查询优化:如果需要频繁查询各科排名,可以单独为每个科目建立排名集合,云函数评分完成后自动更新该集合的文档顺序,查询时直接取前25%条目即可,无需实时排序。
内容的提问来源于stack exchange,提问作者Vincentius Heri
相关产品推荐
相关产品推荐

