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

Node+Express中用Mongoose按用户分组查询最佳分数及分页

解决方案:获取每个用户的最佳分数并支持分页

这个需求完全可以通过MongoDB的聚合框架实现,以下是具体的Mongoose查询方案:

1. 核心聚合查询逻辑

我们可以通过先全局排序,再分组取每组第一条的方式,得到每个用户符合规则的最佳分数:

const bestScoresPerUser = await ScoreModel.aggregate([
  // 第一步:按指定规则全局排序,确保每个用户的最佳分数排在该用户所有记录的最前面
  {
    $sort: {
      milliseconds: 1,    // 优先按耗时升序(越小越好)
      flips: -1,          // 耗时相同则按翻转次数降序(越大越好)
      _id: 1              // 前两者都相同则按文档插入顺序(_id升序)
    }
  },
  // 第二步:按userId分组,取每组的第一条文档(即该用户的最佳分数)
  {
    $group: {
      _id: "$userId",
      bestScore: { $first: "$$ROOT" } // 保留整条文档,也可以单独提取需要的字段
    }
  },
  // 可选:重新整理输出格式,把userId从_id里拿出来
  {
    $project: {
      _id: 0,
      userId: "$_id",
      flips: "$bestScore.flips",
      milliseconds: "$bestScore.milliseconds",
      updatedAt: "$bestScore.updatedAt",
      scoreId: "$bestScore._id"
    }
  }
]);

逻辑说明:

  • 先通过$sort把所有记录按规则排序,这样每个用户的最佳分数会排在该用户所有记录的最前面;
  • 再用$group按userId分组,通过$first取每组的第一条文档,就是该用户的最佳分数;
  • 最后用$project可以按需调整输出字段,让返回结果更简洁。

2. 分页实现

聚合查询支持分页,只需在上述聚合管道的末尾添加$skip和$limit阶段即可:

const page = 1; // 当前页码
const pageSize = 10; // 每页条数

const paginatedBestScores = await ScoreModel.aggregate([
  // 前面的$sort、$group、$project阶段保持不变
  { $sort: { milliseconds: 1, flips: -1, _id: 1 } },
  { $group: { _id: "$userId", bestScore: { $first: "$$ROOT" } } },
  { $project: { _id: 0, userId: "$_id", flips: "$bestScore.flips", milliseconds: "$bestScore.milliseconds" } },
  // 添加分页阶段
  { $skip: (page - 1) * pageSize },
  { $limit: pageSize }
]);

额外优化:

如果需要对分页后的结果再排序(比如按最佳分数的耗时排序展示),可以在$skip之前添加一个额外的$sort阶段,比如:

// 在$skip前添加,按最佳耗时升序展示分页结果
{ $sort: { milliseconds: 1 } }

内容的提问来源于stack exchange,提问作者K. Efkas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 20:05:02