Reputation: 31
I have a map function that returns a value as an array:
emit(doc.created_date, { calories : doc.calories, miles : doc.miles, minutes : doc.minutes, reps : doc.reps, steps : doc.steps, water : doc.water })
I want to run a sum on the calories, miles, minutes and steps for all the returned values. Like
return {"calories":t_cal,"miles":t_mil, "minutes":t_min,"steps":t_step};
I have tried several of the examples the couch wiki and other sites, but i cannot figure out how to access the value array.
I get reduce_overflow_error
when i try just summing the values or a null when running a for loop:
for(var i in values) { t_mil = t_mil + values[i].miles }
Upvotes: 3
Views: 5587
Reputation: 844
You can do it in an elegant and fast way without JS reduce. Make your map function emit an array, like emit(doc.created_date, [doc.calories, doc.miles, doc.minutes, doc.reps, doc.steps, doc.water])
, and then use built-in _sum
for reduce.
Result will be an array of sums by columns. Not well known, however very useful feature of CouchDB.
Upvotes: 4
Reputation: 73702
I do what you are doing a lot, so it is possible.
Either your object is a little bit over CouchDB's limit, or there is a bug in your code.
You can set the CouchDB config, query_server_config/reduce_limit = "false"
and see how it looks.
However, if you are only accumulating four items, I do not think it is a reduce limit issue. What always happens to me is JavaScript problems. For example, adding a number to a string produces a (longer) string. Adding more numbers makes the string longer and longer.
var old_value = "3" // This is a bad value, perhaps from a map function bug
var new_value = 5
new_value = new_value + old_value // I wanted 8, but I got "53"
new_value = new_value + 2012 // I wanted 2020 but I got "532012"
Similar problems occur for arrays and other types.
You have a good start with the map
function emitting the same thing that reduce
returns (an object). Perhaps you could post some code that you are using. I usually do something like this:
function(keys, vals, rereduce) {
// reduce function
var result = {'calories':0, 'miles':0, 'minutes':0, 'steps':0}
for(var i = 0; i < vals.length; i++) {
result.calories += vals[i].calories || 0
result.miles += vals[i].miles || 0
result.minutes += vals[i].minutes || 0
result.steps += vals[i].steps || 0
}
return result
}
Notice that the reduce output is exactly the same as the map output, so this code works for reducing and re-reducing.
Upvotes: 6