Database Reference
In-Depth Information
We'll revisit the group command and all of its other options and idiosyncrasies at the
end of the chapter.
5.3.2
Map-reduce for orders by region
You can think of MongoDB's map-reduce as a more flexible variation on group . With
map-reduce , you have finer-grained control over the grouping key, and you have a
variety of output options, including the ability to store the results in a new collection,
allowing for flexible retrieval of that data later on. Let's use an example to see these
differences in practice.
Chances are that you'll want to be able to generate some sales stats. How many
items are you selling each month? What are the total dollars in sales for each month
over the past year? You can easily answer these questions using map-reduce . The first
step, as the name implies, is to write a map function. The map function is applied to
each document in the collection and, in the process, fulfills two purposes: it defines
which keys which you're grouping on, and it packages all the data you'll need for your
calculation. To see this process in action, look closely at the following function:
map = function() {
var shipping_month = this.purchase_date.getMonth() +
'-' + this.purchase_data.getFullYear();
var items = 0;
this.line_items.forEach(function(item) {
tmpItems += item.quantity;
});
emit(shipping_month, {order_total: this.sub_total, items_total: 0});
}
First, know that the variable this always refers to a document being iterated over. In
the function's first line, you get an integer value denoting the month the order was
created. 10 You then call emit() . This is a special method that every map function must
invoke. The first argument to emit() is the key to group by, and the second is usually
a document containing values to be reduced. In this case, you're grouping by month,
and you're going to reduce over each order's subtotal and item count. The corre-
sponding reduce function should make this more clear:
reduce = function(key, values) {
var tmpTotal = 0;
var tmpItems = 0;
tmpTotal += doc.order_total;
tmpItems += doc.items_total;
return ( {total: tmpTotal, items: tmpItems} );
}
10
Because JavaScript months are zero-based, the month value will range from 0-11. You'll need to add 1 to get
a sensible numerical month representation. Added to this is a - followed by the year. So the keys look like
1-2011, 2-2011, and so on.
Search WWH ::




Custom Search