简体   繁体   中英

Reduce function doesn't seem to work properly

I'm using the function below to extract and create issue objects form all documents of type inspection:

function (doc) {
  if(doc.doctype === "inspection"){
    for(var i=0; i<doc.issues.length; i++) {
      emit(doc.issues[i].id, {id: doc.issues[i].id, status: doc.issues[i].status, date: doc.date});
    }
  }
}

I'm using the id property of each issue as the key to be able to filter the results later by issue. This works properly and returns 4 states for states for the same issue with different dates as follows:

{"total_rows":4,"offset":0,"rows":[
{"id":"31cc62d44e1723f4e39757758101a79a","key":"31cc62d44e1723f4e397577581019612","value":
{"id":"31cc62d44e1723f4e397577581019612","status":"pending","date":"2015-09-02"}},
{"id":"31cc62d44e1723f4e39757758101f808","key":"31cc62d44e1723f4e397577581019612","value":    {"id":"31cc62d44e1723f4e397577581019612","status":"pending","date":"2015-09-16"}},
{"id":"31cc62d44e1723f4e39757758102f70e","key":"31cc62d44e1723f4e397577581019612","value":    {"id":"31cc62d44e1723f4e397577581019612","status":"pending","date":"2015-11-01"}},
{"id":"31cc62d44e1723f4e397577581033cab","key":"31cc62d44e1723f4e397577581019612","value":    {"id":"31cc62d44e1723f4e397577581019612","status":"cancelled","date":"2015-12-07"}}
]}

The problem is that I'm trying to run a reduce function to return only the latest issue and I'm unable to loop through all the values. Although I have 4 rows returned from the map function above the length of the values parameter in the reduce function is 3 using the code below:

function (keys, values, rereduce) {
    return values.length
}

{"rows":[
{"key":null,"value":3}
]}

Also when I try to return the values unchanged to see what's going on I noticed that two of the values have been grouped together as follows:

{"rows":[
{"key":null,"value":[    
[{"id":"31cc62d44e1723f4e397577581019612","status":"pending","date":"2015-11-01"},
{"id":"31cc62d44e1723f4e397577581019612","status":"pending","date":"2015-09-02"}],
[{"id":"31cc62d44e1723f4e397577581019612","status":"cancelled","date":"2015-12-07"}],
[{"id":"31cc62d44e1723f4e397577581019612","status":"pending","date":"2015-09-16"}]]}
]}

Notice that the first two objects have been grouped together in a single array.

I'm really confused and I think it's a simple task but I can't figure out what I'm missing here..

I tried to loop through the values param to compare the date attribute, but that didn't work. I also used the code below to search for the id attribute recursively but it also failed:

function (keys, values, rereduce) {
    var res = [];        
    function extractVal(obj) {
        if(obj.id) {
            res.push(obj.id);
        }else {
            for(key in obj) {
                extractVal(obj[key]);
            }
        }
    }

    extractVal(values);
    return res;
}

Ok, This is what I figured out and please correct me if I'm wrong.

The reduce function runs several times with the rereduce value = false, and finally it runs on last time with the rereduce value = true. So if I just returned the values array as it is in the condition where rereduce is false I will get an array of those returned arrays as the values parameter in the final step where the rereduce = true.

And therefore to extract the objects that were returned in the map function I need to run a nested loop as follows:

function (keys, values, rereduce) {
    var arr=[];
    if(rereduce){
        for(var i=0; i<values.length; i++) {
            for(var j=0; j<values[i].length; j++) {
                arr.push(values[i][j]);
            }
        }
        return arr;
    } else{
        return values;
    }
}

And finally instead of just returning the arr parameter I will process it to filter whaterver should be returned by the reduce function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM