Поведение CouchDB при неожиданном сокращении / перезапуске

#mapreduce #couchdb

#mapreduce #couchdb

Вопрос:

Я предполагаю, что я неправильно рассматриваю проблему, но, похоже, я неожиданно сталкиваюсь с rereduce

Упрощенным примером моей проблемы может быть табель успеваемости студента

Данные (в табличном формате для удобства чтения)

 Entered     Student  Assig   Grade
2019-02-01  Alice        1    0.80
2019-03-01  Alice        2    0.50
2019-04-01  Alice        2    0.80
2019-04-01  Alice        3    0.80
  

История, связанная с данными, заключается в том, что Алиса хорошая ученица, но преподаватель неправильно ввел данные. Алиса, указала на это преподавателю, который затем внес поправку в отчет об оценке. По причинам учета записи могут не удаляться, но могут быть добавлены обновленные записи.

Карта:

 function(doc){
    var key = [doc.student,doc.assig];
    var val = {
        grade:doc.grade,
        entered: doc.entered
    };
    emit(key,val);
}
  

Тогда при сокращении преследуются две цели:

  1. Возьмите самую последнюю введенную оценку
  2. Соберите stats оценки
 function(keys,values,rereduce){
    if(rereduce){
        return sum(values);
    }
    else{
        value = values.pop();
        for(var v in values){
            v = values[v];
            if(v.entered > value.entered){
                value = v;
            }
        }
        return value.grade;
    }
}
  

В ту минуту, когда я подаю заявку group=true , я ожидаю получить список самых последних оценок для каждого задания. Вместо этого я получаю суммы всех оценок.

 Key           Actual   Expected
["Alice",1]     0.8       0.8
["Alice",2]     1.3       0.8
["Alice",3]     0.8       0.8
  

Как ни странно, дальнейшее сокращение:

 Key           Actual   Expected
["Alice"]       2.4       2.4
  

Я в замешательстве. Как я запутался?

(CouchDB v2.3)

Редактировать

Хорошо, итак, я понимаю, почему я ошибся (переполненные индексы), но теперь мне интересно, как это исправить…

http://guide.couchdb.org/draft/views.html#reduce

Я также все еще очень смущен поведением group_leve 1 и 2.

Ответ №1:

Я подозреваю, что происходит то, что я использую неправильный инструмент для работы. Сокращения в CouchDB работают лучше всего, когда у них есть одно задание.

В конечном итоге было использовано решение создать update функцию, которая просто добавляет новую оценку к массиву в существующем документе.

В значительной степени основано на моменте RTFM: https://docs.couchdb.org/en/stable/ddocs/views/collation.html

 Student  Assig   Grades
Alice        1    [{e:'2019-02-01',g:0.80}]
Alice        2    [{e:'2019-04-01',g:0.80},{e:'2019-03-01',g:0.50}]
Alice        3    [{e:'2019-04-01',g:0.80}]
  

Карта изменяется на…

 function(doc){
    var key = [doc.student,doc.assig];
    var val = doc.grades.shift().grade;
    emit(key,val);
}
  

… и сокращение может использовать встроенные функции сокращения.

Единственное, что упущено, это то, что изменения в данных не так очевидны, однако a просто создать представление для отчета об этом:

 function(doc){
    for(var val in doc.grades){
        var key = [doc.student,doc.assig,val.entered];
        emit(key,val.grade);
    }
}
  

Теперь пользователи имеют доступ как к подробному списку изменений, так и к агрегированным результатам.

Приведенный выше код не тестировался, поскольку это тривиальный пример проблемы. Концептуально это правильно; синтаксически я ожидаю проблем.