CouchDB — агрегировать несколько значений на шаге уменьшения

#mapreduce #couchdb

#mapreduce #couchdb

Вопрос:

Я пытаюсь агрегировать несколько значений, передаваемых с моей карты, в пользовательской функции уменьшения (включена функция повторного уменьшения), но в результате я получаю нулевые значения, за исключением нескольких точек данных, где я вижу 0. Любая помощь очень ценится. Спасибо

Мои передаваемые данные представлены в этом формате:

 Key:"dateX" Values:"{'a':435, 'b':5645}"
Key:"dateX" Values:"{'a':8451, 'b':9245}"
Key:"dateX" Values:"{'a':352, 'b':450}"

Key:"dateY" Values:"{'a':5675, 'b':1245}"
Key:"dateY" Values:"{'a':4455, 'b':620}"
  

Я хочу агрегировать / суммировать значения как a, так и b для dateX и dateY, мой map-reduce:

 "map": "function(doc){emit(doc.logDate, {'a': doc.a, 'b': doc.b} );}",

"reduce": "function(key, values, rereduce) { 
                    var total = {tA:0, tB:0}; 
                    if(rereduce){ 
                        for(i=0; i<values.length; i  )
                        { 
                            total.tA  = values[i].a; 
                            total.tB  = values[i].b;
                        } 
                        return total;
                    } 
                    total.tA = sum(values.a); 
                    total.tB = sum(values.b); 
                    return total; }"
------------------------
Results:
dateX        {tA: 0, tB: 0} 
dateY        {tA: null, tB: null}   
dateZ        {tA: null, tB: null}
        .
        .
        .   
  

Ответ №1:

Прежде всего, функция sum ожидает массив в качестве аргумента вместо значений.a который не определен, поэтому вы можете попробовать

 total.tA = sum(values.map(function (value) {return value.a}));
total.tB = sum(values.map(function (value) {return value.b}));
  

Или что-то вроде

 values.reduce(function (t, value) {
    t.tA  = value.a;
    t.tB  = value.b;
    return t;
}, total);
  

Кроме того, когда включен флаг повторного уменьшения, это означает, что функция уменьшения работает с уже уменьшенными значениями, поэтому

 for (i=0; i < values.length; i  ) { 
    total.tA  = values[i].tA; //not a
    total.tB  = values[i].tB; //not b
}
  

Кроме того, вы должны добавить else , чтобы предотвратить двойное выполнение в случае повторного использования

 if (rereduce) {
   //
} else {
  //
}
  

http://guide.couchdb.org/editions/1/en/views.html#reduce

Комментарии:

1. Спасибо @the4lt, я попробую это, для моей проблемы я исправил ее, создав {tA:0, tB: 0}; в том же формате, что и»{‘a’:4455, ‘b’: 620}», таким образом, метод reduce работает правильно, и я предполагаю, что это такне запускать повторное вычисление, поэтому я могу суммировать с помощью цикла for и избегать функции sum() для агрегирования.