I'm trying to aggregate some data I have in CouchDB. There are photo documents in the database and rating documents in the database. Each rating document looks like so (sans _id and _rev):
{
"type": "rating",
"rating": 3 // Integer values are identifiers that map to a string; e.g 1 might mean 'funny'
"photo": "as9i83ufsafa09uj" // The id of the photo that this rating points to.
}
What I want to do is a get a count of each rating type for each photo.
{
"key": "as9i83ufsafa09uj", "value": [1, 7, 8, 6] // 1 '0' rating, 7 '1' ratings, etc.
"key": "photoid2", "value": [3, 0, 0, 8]
}
I'm using CouchDB views' MapReduce to achieve this aggregation.
"map": "function(doc) {
if(doc.type == 'rating')
{
emit(doc.photo, doc.rating);
}
}",
"reduce": "function(keys, values, rereduce) {
var result = new Array(0, 0, 0, 0);
values.forEach( function(key, value)
{
result[value]+=1;
});
return result;
}"
The map returns:
{"total_rows":55,"offset":0,"rows":[
{"id":"0aa2c4c9a031eedbcf2795cabc1679be","key":"4aa5ec26-26b8-490a-a9cc-620a0d2136b9","value":0},
{"id":"29f363432e008f5934b4160292e18680","key":"4aa5ec26-26b8-490a-a9cc-620a0d2136b9","value":3},
{"id":"646d0d764623bc2f3ed1354ac03b583e","key":"4aa5ec26-26b8-490a-a9cc-620a0d2136b9","value":2},
...
{"id":"fa5be78402171e3bf1eb1cf91c5fda6e","key":"c63b78b6-ad92-426c-ab64-c9a6ae229b31","value":1}
]}
The reduce returns witb group_level=0:
{"rows":[
{"key":null,"value":[1,1,1,1]}
]}
with group_level=1:
{"rows":[
{"key":"4aa5ec26-26b8-490a-a9cc-620a0d2136b9","value":[2,2,2,0]},
{"key":"5ad3de4b-d25b-42d3-95e0-df7661becbf3","value":[2,2,2,2]},
{"key":"7600710b-9ae3-4312-876c-ad352722dac3","value":[2,2,2,2]},
{"key":"959f48a2-5018-4938-aab4-086d8824dd75","value":[2,0,0,0]},
{"key":"c63b78b6-ad92-426c-ab64-c9a6ae229b31","value":[2,2,2,2]}
]}
I'm familiar with MongoDB's map reduce and this function would work using their schema. What do I need to tweak for this to work in CouchDB?
UPDATE This is the final reduce function that worked for me. I wasn't addressing the rereduce parameter correctly. Thanks goes to Marcin Skórzewski for helping me to better understand rereduce.
"reduce": "function(key, values, rereduce) {
var result = new Array(0, 0, 0, 0);
if(rereduce == true)
{
for(var i = 0; i < values.length; i++)
{
var value = values[i];
for (var j = 0; j < value.length; j++)
{
result[j] += value[j];
}
}
return result;
}
for(var i = 0; i < values.length; i++)
{
value = values[i];
result[value]+=1;
}
return result;
}"