MapReduce and aggregation
MapReduce and aggregation
MapReduce is a legacy MongoDB feature deprecated since version 5.0. Prefer aggregation pipelines for new work and translate existing grouping logic into stages.
MongoDB provides two powerful tools for processing and transforming data: MapReduce and the Aggregation Framework. Both are used to perform operations like grouping, filtering, and summarizing data. However, they differ in syntax, performance, and use cases.
Before working through the examples, make sure you can connect with mongosh and select your database. Use a practice database for writes and deletions.
Legacy feature: MongoDB deprecated MapReduce in version 5.0 and recommends aggregation pipelines for new work. The MapReduce code below explains older applications; it is not the recommended starting point. See the official MapReduce documentation.
By the end of this lesson
Compare legacy MapReduce with an aggregation pipeline that produces the same summary.
What is MapReduce?
MapReduce is a data processing model borrowed from distributed systems like Hadoop. It consists of two main steps:
- Map: Processes each document and emits key-value pairs
- Reduce: Groups those key-value pairs and applies aggregation logic
What is Aggregation Framework?
The Aggregation Framework uses a pipeline-based approach, where data passes through multiple stages such as $match, $group, $sort, and $project. It's much faster and easier to use compared to MapReduce in most scenarios.
Example Dataset
Let’s use a sample collection orders:
db.orders.insertMany([
{ customer: "Alice", amount: 250 },
{ customer: "Bob", amount: 400 },
{ customer: "Alice", amount: 150 },
{ customer: "Bob", amount: 100 },
{ customer: "Charlie", amount: 300 }
])Goal
We want to calculate the total amount spent by each customer.
Using Aggregation Framework
db.orders.aggregate([
{
$group: {
_id: "$customer",
totalSpent: { $sum: "$amount" }
}
}
])
[
{ "_id": "Alice", "totalSpent": 400 },
{ "_id": "Bob", "totalSpent": 500 },
{ "_id": "Charlie", "totalSpent": 300 }
]
Explanation: The $group stage groups documents by customer name and calculates the sum of their amount fields.
Using MapReduce
var mapFunction = function() {
emit(this.customer, this.amount);
};
var reduceFunction = function(key, values) {
return Array.sum(values);
};
db.orders.mapReduce(
mapFunction,
reduceFunction,
{ out: "order_totals" }
)
db.order_totals.find().pretty()
{
"_id": "Alice",
"value": 400
}
{
"_id": "Bob",
"value": 500
}
{
"_id": "Charlie",
"value": 300
}
Explanation: The map function emits each customer and their order amount. The reduce function adds up all values for each customer. The result is stored in a new collection order_totals.
Intuition Check
Q: Which one should I use if I just want to sum values or filter records?
A: Use the Aggregation Framework. It’s faster, more concise, and optimized for simple tasks like grouping, filtering, and projecting data.
Performance Comparison
- Aggregation Framework: Faster, native, uses internal pipeline optimization
- MapReduce: Slower, uses JavaScript functions, not suitable for large-scale aggregation in most cases
Legacy MapReduce use cases
MapReduce can still be useful when:
- You need complex logic that can’t be expressed using aggregation stages
- You want to perform custom JavaScript-based transformations
What to remember
MapReduce is a legacy MongoDB feature deprecated since version 5.0. Prefer aggregation pipelines for new work and translate existing grouping logic into stages.
Summary
- Use Aggregation Framework for most common tasks — it’s faster and easier to use
- Use MapReduce only when aggregation can’t handle your logic
- Aggregation outputs directly, MapReduce stores results in a separate collection
Reaching the recap and completing the quizzes are separate milestones.