#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);
}
Тогда при сокращении преследуются две цели:
- Возьмите самую последнюю введенную оценку
- Соберите
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);
}
}
Теперь пользователи имеют доступ как к подробному списку изменений, так и к агрегированным результатам.
Приведенный выше код не тестировался, поскольку это тривиальный пример проблемы. Концептуально это правильно; синтаксически я ожидаю проблем.