CouchDB 意外 reduce/rereduce 行为
CouchDB unexpected reduce/rereduce behaviour
我假设我看错了问题,但我似乎意外地击中了 rereduce
我的问题的一个简化示例是学生成绩单
数据(采用table格式以便于阅读)
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 的行为仍然很困惑。
我怀疑是因为我在工作中使用了错误的工具。当他们只有一份工作时,减少在 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);
}
...并且 reduce 可以使用内置的 reduce 函数。
唯一丢失的是对数据的修改不那么明显,但是创建一个视图来报告它很简单:
function(doc){
for(var val in doc.grades){
var key = [doc.student,doc.assig,val.entered];
emit(key,val.grade);
}
}
现在用户可以访问更改的详细列表以及汇总结果。
上面的代码未经测试,因为它是一个简单的问题示例。从概念上讲,它是正确的;在句法上,我预计会出现问题。
我假设我看错了问题,但我似乎意外地击中了 rereduce
我的问题的一个简化示例是学生成绩单
数据(采用table格式以便于阅读)
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 的行为仍然很困惑。
我怀疑是因为我在工作中使用了错误的工具。当他们只有一份工作时,减少在 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);
}
...并且 reduce 可以使用内置的 reduce 函数。
唯一丢失的是对数据的修改不那么明显,但是创建一个视图来报告它很简单:
function(doc){
for(var val in doc.grades){
var key = [doc.student,doc.assig,val.entered];
emit(key,val.grade);
}
}
现在用户可以访问更改的详细列表以及汇总结果。
上面的代码未经测试,因为它是一个简单的问题示例。从概念上讲,它是正确的;在句法上,我预计会出现问题。