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

如何加速按分类获取最新2条文档的MongoDB聚合查询?

解决MongoDB按分类取最新文档的性能问题

嘿,我来帮你搞定这个查询慢的难题!你的场景是数百万文档、日增数千条,要取每个分类下最新2条,现有的单字段索引确实不够用——这就是速度慢的核心原因,下面给你一步步的优化方案:

一、先搞懂现有索引的问题

你现在创建的是{time:-1}和{category:1}两个单字段索引,但MongoDB没法高效把这两个索引结合起来完成「按分类分组+取最新N条」的查询。它要么先扫全表按time排序,再分组;要么先按category找全部分类,再每个分类单独排序,这两种方式都会带来大量的IO和计算,自然慢得离谱。

二、核心优化:创建复合索引

直接创建**{category: 1, time: -1}的复合索引**,这是解决问题的关键!

db.testing.createIndex({category: 1, time: -1})

这个索引的逻辑是:先按category升序把所有文档分组,每个分组内的文档又按time降序排列——这样每个分类下的最新文档直接就在分组的最前面,取前2条根本不需要额外排序,MongoDB可以直接从索引里捞数据,性能会提升N个档次。

三、优化查询语句(两种方案可选)

根据你的MongoDB版本,选对应的高效查询方式:

方案1:通用版(支持所有MongoDB版本)

用聚合框架的$group+$push+$slice组合,配合上面的复合索引,性能会比你之前的查询好很多:

db.testing.aggregate([
  // 利用复合索引完成排序,避免内存排序
  { $sort: { category: 1, time: -1 } },
  // 按分类分组,把每个分类的文档按时间顺序存入数组
  { $group: {
      _id: "$category",
      latestDocs: { $push: "$$ROOT" }
    }
  },
  // 截取每个分类数组的前2条最新文档
  { $project: {
      _id: 0,
      category: "$_id",
      latestDocs: { $slice: ["$latestDocs", 2] }
    }
  }
])

⚠️ 注意:如果某个分类下的文档特别多(比如几十万条),$push会占用较多内存,这时候推荐用下面的方案2。

方案2:高性能版(MongoDB 5.0+支持)

用$setWindowFields窗口函数,它能直接利用复合索引计算每个文档在分类内的排名,不需要把整个分类的文档都存入数组,内存占用更低,性能更优:

db.testing.aggregate([
  // 按分类分区,每个分区内按时间降序计算排名
  { $setWindowFields: {
      partitionBy: "$category",
      sortBy: { time: -1 },
      output: {
          rank: { $rank: {} }
      }
    }
  },
  // 只保留每个分类下排名前2的文档
  { $match: { rank: { $lte: 2 } } },
  // 按分类整理结果(可选,根据你的输出需求调整)
  { $group: {
      _id: "$category",
      latestDocs: { $push: "$$ROOT" }
    }
  },
  // 移除临时的rank字段,整理输出格式
  { $project: {
      _id: 0,
      category: "$_id",
      latestDocs: { $map: {
          input: "$latestDocs",
          as: "doc",
          in: { $unset: ["$$doc.rank"] }
        }
      }
    }
  }
])

四、额外优化建议

  • 验证索引是否生效:在聚合语句末尾加.explain("executionStats"),查看查询计划,确认是否用到了我们创建的复合索引,避免出现全表扫描的情况。
  • 清理旧数据:如果不需要保留所有历史文档,定期删除过期数据,减少集合体积,能显著提升查询速度。
  • 分片考虑:如果数据量持续增长到数亿级别,可以考虑按category或time分片,把数据分散到多个节点,进一步提升查询效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:31:15