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

MongoDB多$project阶段聚合百分比查询优化咨询

MongoDB聚合查询优化建议(技能需求占比计算)

需求背景

计算过去90天内各技能的需求占比,现有查询可得到预期结果,但存在优化空间。

示例文档

{
   "_id": { "$oid": "630a2ba9fe850ebc2d2f4a25" },
   "category": {
      "name": "SQL",
      "path": ",web development,",
      "id": { "$oid": "62fe35f3f1793d2014bfe05f" }
   },
   "createdAt": { "$date": { "$numberLong": "1661610921812" } }
}

原查询存在的问题

  1. 窗口函数写法不规范:第一个$project阶段中total: {$sum:count}属于隐式窗口函数用法,未明确声明窗口范围,可读性差,后续维护易出错。
  2. 冗余管道阶段:分两个$project阶段处理占比计算,增加了不必要的管道处理开销。
  3. 性能优化缺失:未针对$match阶段的createdAt字段创建索引,数据量较大时过滤速度慢。

优化后的查询

// 提前计算90天前的时间,避免管道内重复计算
const ninetyDaysAgo = new Date(Date.now() - 90 * 24 * 60 * 60 * 1000);

const SkillsInDemand = await Job.aggregate([
  // 过滤过去90天数据,依赖索引加速
  { $match: { createdAt: { $gte: ninetyDaysAgo } } },
  // 分组统计各技能的需求数量
  {
    $group: {
      _id: "$category.name",
      count: { $sum: 1 }
    }
  },
  // 用窗口函数计算所有技能的总需求数,每个文档都能获取该值
  {
    $setWindowFields: {
      output: {
        total: { $sum: "$count" }
      }
    }
  },
  // 计算占比并格式化结果(保留2位小数可选)
  {
    $project: {
      _id: 1,
      percentage: {
        $round: [ { $multiply: [ { $divide: ["$count", "$total"] }, 100 ] }, 2 ]
      }
    }
  },
  // 按占比降序排序
  { $sort: { percentage: -1 } }
]);

优化说明

  • 索引优化:给createdAt字段创建单字段索引,大幅提升$match阶段的数据过滤速度:
    db.Job.createIndex({ createdAt: 1 })
    
  • 清晰的窗口函数用法:使用$setWindowFields明确计算总需求数,逻辑直观,可读性强。
  • 减少管道阶段:合并原查询的两个$project阶段,降低管道处理的性能开销。
  • 结果格式化:通过$round函数将百分比保留2位小数,输出结果更整洁(可根据需求调整小数位数)。

优化后输出示例

[
  { "_id": "Python", "percentage": 75 },
  { "_id": "SQL", "percentage": 16.67 },
  { "_id": "Flutter", "percentage": 8.33 }
]

内容的提问来源于stack exchange,提问作者Fawad 4bros

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 13:06:28