Reputation: 65
I have CouchDB view that gives me a correct value in natural order and a null when sorted descending, here are the Futon screenshots:
Here is the view code:
"informe_precios": {
"map": "function(doc){if(doc.doc_type=='precio'){emit([doc.comprador,doc.fecha.substr(0,4),doc.fecha.substr(5,2)],{precio:doc.precio,litros:doc.litros});}}",
"reduce": "function(keys, values, rereduce){var importe= 0; var totallitros = 0;for(var i = 0; i < values.length; i++) {importe += values[i].precio*values[i].litros;totallitros += values[i].litros;}return importe/totallitros;}"
}
I need it descending because I want to get 12 last values.
TIA Diego
Upvotes: 2
Views: 497
Reputation: 27961
You're always assuming that your reduce
function is called with the output of your map
function, ie. you're not handling the rereduce
situation.
In the rereduce
your values
will be the importe/totallitros
values from previous reduce
calls.
Your reduce function is getting a "price per liter" average for each month, so because it's an average there's no way for your rereduce
function to actually handle that data because for the multiple values
coming in there's no way to know their weight in the average.
So, you'll need to change your function to return the count so that you can use that to weight the average in the rereduce
function (we're also using the inbuilt sum
function to make things simpler):
function(keys, values, rereduce) {
if (rereduce) {
var length = sum(values.map(function(v){return v[1]}));
var avg = sum(values.map(function(v){
return v[0] * (v[1] / length)
}));
return [avg, length];
}
else {
var importe= 0;
var totallitros = 0;
for( var i = 0; i < values.length; i++) {
importe += values[i].precio * values[i].litros;
totallitros += values[i].litros;
}
return [ importe/totallitros, values.length ];
}
}
The final result you'll see in your view here will be an array, so you'll always need to pick out the first element of that in your client code.
Upvotes: 1