如何用MongoDB聚合管道实现分组内排名?

陌雪小哥_6677

陌雪小哥_6677

2026-08-09

232人浏览

原创

$rank 不能直接用于 $group 后,因其是仅在 5.0+ 的 $setwindowfields 中支持的窗口函数,需配合 $sort 和 partitionby 使用;老版本需用 $push + $indexofarray 模拟,但有性能与并列处理限制。

如何用mongodb聚合管道实现分组内排名?

为什么 $group 后不能直接用 $rank?

因为 $rank 是 window 函数,只在 5.0+ 版本的 $setWindowFields 阶段中可用,且必须配合 $sort 和分组上下文(partitionBy)使用。直接写在 $group 后面会报错:"unknown operator: $rank"。老版本(如 4.4 及之前)压根不支持窗口函数,只能靠变通方式模拟。

用 $setWindowFields 实现分组内 Top-N 排名(5.0+)

这是最干净、最符合语义的做法,但要注意三点:排序字段类型必须一致、partitionBy 字段必须有索引、整个阶段不能放在 $lookup 或 $unwind 之后(否则分组逻辑被破坏)。

例如:按 category 分组,对每个分组内按 sales 降序排前 3 名:

[
  { $match: { sales: { $exists: true, $type: "number" } } },
  { $sort: { category: 1, sales: -1 } },
  {
    $setWindowFields: {
      partitionBy: "$category",
      sortBy: { sales: -1 },
      output: {
        rank: { $rank: {} },
        denseRank: { $denseRank: {} }
      }
    }
  },
  { $match: { rank: { $lte: 3 } } }
]
  • $sort 必须紧邻 $setWindowFields 前,且方向与 sortBy 一致,否则排名错乱
  • partitionBy 字段若基数高(如用户 ID),建议在该字段上建索引:db.orders.createIndex({ category: 1 })
  • $match 放在最后才能真正“裁剪”,否则 $setWindowFields 仍会对全量数据计算排名

兼容老版本的 fallback 方案:$push + $indexOfArray

适用于 MongoDB 4.2–4.4,核心思路是:先分组聚合出有序数组,再用 $indexOfArray 查当前文档在数组中的位置。缺点是内存占用高、无法处理并列($rank vs $denseRank),且文档数超万时易触发 maxMemoryUsageMB 限制。

mongodb-query
mongodb-query

用于调试和故障排查,查询MongoDB数据库。用户需要时可以: (1) 列出所有数据库; (2) 列出数据库中的集合; (3) 执行MongoDB查询或命令。

下载

示例:给每个 category 内销量最高的 3 条记录打上 rank 标签:

[
  { $match: { sales: { $type: "number" } } },
  {
    $group: {
      _id: "$category",
      topItems: {
        $push: {
          _id: "$_id",
          sales: "$sales",
          name: "$name"
        }
      }
    }
  },
  { $unwind: { path: "$topItems", includeArrayIndex: "rankIdx" } },
  {
    $addFields: {
      rank: { $add: ["$rankIdx", 1] }
    }
  },
  { $project: { _id: "$topItems._id", name: "$topItems.name", sales: "$topItems.sales", rank: 1 } },
  { $match: { rank: { $lte: 3 } } }
]
  • 必须先 $group 再 $unwind,否则 includeArrayIndex 不生效
  • $push 默认按输入顺序追加,所以务必在 $group 前加 $sort(如 { $sort: { category: 1, sales: -1 } })
  • 如果原始集合没按 category 排序,$group 输出的 topItems 数组顺序不可控

最容易被忽略的坑:字段类型和索引缺失

真正让分组内排名慢或不准的,往往不是语法写错,而是底层数据“不干净”:

  • sales 字段存成字符串("1200")而非数字,$sort 会按字典序排,“999” > “10000”
  • category 字段存在 null 或空字符串,$group 会把它们全归到同一个 _id: null 分组里
  • 没在 category 和 sales 上建复合索引:db.orders.createIndex({ category: 1, sales: -1 }),导致 $sort 阶段无法流式执行,全量入内存
  • 在 $lookup 后做排名——关联结果已打乱原始顺序,且 $setWindowFields 不支持跨集合分区

上线前务必跑一次 explain("executionStats"),重点看 stage 是否出现 COLLSCAN、sortStage 的 memUsage 是否超限、usedDisk 是否为 true。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

mongodb

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
mongodb和mysql的区别
mongodb和mysql的区别

mongodb和mysql的区别:1、数据模型;2、查询语言;3、扩展性和性能;4、可靠性。本专题为大家提供mongodb和mysql的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

815

5

mongodb启动命令
mongodb启动命令

MongoDB 是一种开源的、基于文档的 NoSQL 数据库管理系统。本专题提供mongodb启动命令的文章,希望可以帮到大家。

2023.08.08

2874

5

MongoDB删除数据的方法
MongoDB删除数据的方法

MongoDB删除数据的方法有删除集合中的文档、删除整个集合、删除数据库和删除指定字段等。本专题为大家提供MongoDB相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.19

2744

5

常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.02

4529

19

mongodb有哪些应用领域
mongodb有哪些应用领域

mongodb 的应用领域涵盖广泛,包括内容管理系统、社交媒体、分析、移动应用、物联网、金融科技、医疗保健和广告技术等领域,因其灵活性、可扩展性和易用性而广受欢迎。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.02

978

6

mongodb和redis哪个读取速度快
mongodb和redis哪个读取速度快

redis 的读取速度比 mongodb 更快。原因包括:1. redis 使用简单的键值存储,而 mongodb 存储 json 格式的数据,需要解析和反序列化。2. redis 使用哈希表快速查找数据,而 mongodb 使用 b-tree 索引。因此,redis 在需要高性能读取操作的应用程序中是一个更好的选择。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.02

7572

6

mongodb安装失败如何彻底删除
mongodb安装失败如何彻底删除

彻底删除 mongodb 安装失败的步骤:1、停止和禁用 mongodb 服务;2、删除配置文件、数据目录和日志文件;3、删除 mongodb 二进制文件;4、卸载 mongodb 套件(如果通过软件包管理器安装);5、删除 mongodb 用户、组和目录;6、重启系统。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.02

595

6

mongodb与mysql好用推荐
mongodb与mysql好用推荐

mongodb 适用于非结构化数据、高扩展性和灵活查询(如网站内容管理、社交媒体),而 mysql 适用于结构化数据、强数据一致性和联接查询(如电子商务、银行系统)。

2024.04.02

2269

9

mongodb数据库的优势有哪些
mongodb数据库的优势有哪些

mongodb 数据库以其灵活、可扩展和高性能而闻名。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.08

2551

6

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MongoDB 教程
MongoDB 教程

共17课时 | 6.4万人学习

黑马云课堂mongodb实操视频教程
黑马云课堂mongodb实操视频教程

共11课时 | 3.5万人学习

MongoDB 教程
MongoDB 教程

共42课时 | 61.7万人学习