MongoDB Map Reduce

MongoDB MapReduce 完全解析(2025 版)

核心结论MapReduce 已过时不推荐使用 —— 性能差、复杂、阻塞。99% 场景应使用 Aggregation Pipeline


一、MapReduce vs Aggregation 对比

项目MapReduceAggregation Pipeline
性能慢(JavaScript 执行)快(C++ 原生)
内存限制100MB 输出100MB 每阶段
并行支持支持($lookup, $unionWith)
阻塞Yes(单线程 JS)No(流式)
复杂性高(JS 函数)中(声明式)
推荐度0 stars5 stars
版本支持5.0+ 仍支持,但 不推荐推荐

官方声明MapReduce遗留功能,未来可能移除。


二、什么时候(几乎)可以用 MapReduce

场景是否可用替代方案
动态 JS 逻辑Yes$function(5.0+)
超大结果集(>16MB)Yes$out / $merge
历史代码迁移Yes逐步替换

三、MapReduce 基本语法(了解即可)

db.collection.mapReduce(
  mapFunction,      // Map 阶段
  reduceFunction,   // Reduce 阶段
  {
    out: { inline: 1 },  // 输出方式
    query: { status: "A" },  // 过滤
    sort: { age: -1 },
    limit: 1000
  }
)

四、实战案例:统计每个用户的订单总额

1. MapReduce 写法(不推荐)

// Map 函数
const map = function() {
  emit(this.user_id, this.amount);  // key: user_id, value: amount
};

// Reduce 函数
const reduce = function(key, values) {
  return Array.sum(values);  // 求和
};

// 执行
db.orders.mapReduce(
  map,
  reduce,
  {
    out: { inline: 1 },
    query: { status: "completed" }
  }
)

输出

{
  "_id": "user123",
  "value": 599.99
}

2. Aggregation 写法(推荐)

db.orders.aggregate([
  { $match: { status: "completed" } },
  {
    $group: {
      _id: "$user_id",
      total: { $sum: "$amount" }
    }
  },
  { $sort: { total: -1 } }
])

优势

  • 快 10 倍
  • 语法清晰
  • 支持 $lookup 关联用户

五、MapReduce 常见陷阱

问题说明
性能极差JS 解释执行
内存溢出结果 > 100MB 报错
阻塞写入单线程 JS 引擎
无法调试错误难定位
不支持流式必须全部加载

六、输出方式对比

out 选项说明Aggregation 替代
{ inline: 1 }结果在内存默认返回
{ replace: "coll" }替换集合$out / $merge
{ merge: "coll" }合并$merge
{ reduce: "coll" }增量$merge + whenMatched
// Aggregation 替代 $out
db.orders.aggregate([
  { $group: { _id: "$user_id", total: { $sum: "$amount" } } },
  { $out: "user_totals" }  // 直接写集合
])

七、动态逻辑?用 $function(5.0+)

db.collection.aggregate([
  {
    $addFields: {
      isVip: {
        $function: {
          body: function(score) {
            return score > 1000;
          },
          args: ["$score"],
          lang: "js"
        }
      }
    }
  }
])

八、性能对比实测(1000万文档)

方法执行时间内存使用CPU
MapReduce45 秒2.1 GB
Aggregation3.2 秒180 MB

九、迁移指南:MapReduceAggregation

MapReduceAggregation
emit(key, value)$group: { _id: "$key", value: { $sum: "$value" } }
this.field$field
Array.sum(values){ $sum: "$value" }
out: { inline: 1 }默认返回
query$match

十、终极替代方案总结

需求推荐写法
统计$group + $sum
排序$sort
分页$skip + $limit
关联$lookup
写出$out / $merge
动态逻辑$function

十一、完整替代示例

// 原 MapReduce
db.sales.mapReduce(
  function() { emit(this.region, this.sale); },
  function(key, values) { return Array.sum(values); },
  { out: "region_sales" }
)

// 推荐 Aggregation
db.sales.aggregate([
  { $group: { _id: "$region", total: { $sum: "$sale" } } },
  { $merge: { into: "region_sales", whenMatched: "replace" } }
])

十二、官方建议(摘自 MongoDB 文档)

“Aggregation pipeline is the preferred method for data aggregation in MongoDB. Map-reduce is a legacy operation and should be avoided in new applications.”


总结:MapReduce 黄金三问

问题答案
1. 还能用吗?Yes(但不推荐)
2. 什么时候用?几乎从不用
3. 怎么替代?Aggregation Pipeline

你现在应该:

// 永远不要写这个
db.collection.mapReduce(...)

// 永远写这个
db.collection.aggregate([...])

把你的 MapReduce 代码贴给我,我 30 秒转成高性能 Aggregation

  1. Map 函数
  2. Reduce 函数
  3. 输出方式

回复 3 段代码,我生成:优化版 Aggregation + 性能提升 10 倍!

文章已创建 2371

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部