Mapreduce 映射/减少以获取按键分组的每个文档的计数和最新日期
我的文档的简单版本如下所示: 文件: 我想按键对文档进行分组,以获取每个键的最新日期和文档数,例如Mapreduce 映射/减少以获取按键分组的每个文档的计数和最新日期,mapreduce,couchbase,Mapreduce,Couchbase,我的文档的简单版本如下所示: 文件: 我想按键对文档进行分组,以获取每个键的最新日期和文档数,例如 { "Last": "2014-04-16T16:00:00", "Count": 10 } 我的想法是将“映射/减少视图和查询”设置组设置为true。 这就是我迄今为止所尝试的。我知道确切的数字,但不是正确的日期 地图 减少 函数(键、值、返回值){ var结果={ 最后:0,, 计数:0 }; 如果(减少){ 对于(变量i=0;iresult.Last?值[i].Last:result.La
{ "Last": "2014-04-16T16:00:00", "Count": 10 }
我的想法是将“映射/减少视图和查询”设置组设置为true。这就是我迄今为止所尝试的。我知道确切的数字,但不是正确的日期 地图 减少
函数(键、值、返回值){
var结果={
最后:0,,
计数:0
};
如果(减少){
对于(变量i=0;i
您没有比较日期。。。Couchbase按键对值进行排序。在您的情况下,它不会按日期排序,因此您应该在reduce函数中手动进行排序。可能会是这样的:
result.Last=值[i]。Last>result.Last?值[i].Last:result.Last;
在reduce函数中,它也可以是数组,所以我不认为reduce函数总是正确的
下面是我的reduce函数的一个示例,它过滤文档并只留下一个具有最新日期的文档。也许它会有帮助,或者你可以尝试使用它(看起来像是你想要的reduce函数,你只需要在某处添加count)
函数(k,v,r){
if(r){
如果(v.长度>1){
var m=v[0]。日期;
var-mid=0;
对于(var i=1;i m){
m=v[i]。日期;
mid=i;
}
}
返回v[mid];
}
否则{
返回v[0]| | v;
}
}
如果(v.长度>1){
var m=v[0]。日期;
var-mid=0;
对于(var i=1;i m){
m=v[i]。日期;
mid=i;
}
}
返回v[mid];
}
否则{
返回v[0]| | v;
}
}
UPD:以下是reduce的一个示例:
该函数的输入日期(值)如下所示(我只使用了数字而不是文本日期来缩短它):
[{Date:1},{Date:3},{Date:8},{Date:2},{Date:4},{Date:7},{Date:5}]
在第一步中,rereduce将是false
,因此我们需要找到数组中最大的日期,它将返回
对象{Date:8}
请注意,此函数可以一次调用,但它可以在集群中的多个服务器上调用,也可以在一个couchbase实例中的多个b树分支上调用
然后在下一步中(如果集群或“分支”中有多台机器),将调用rereduce
,并且rereduce
var将设置为true
传入数据将是:
[{Date:8},{Date:10},{Date:3}]
,其中{Date:8}
来自一个服务器(或分支)的reduce,其他日期来自另一个服务器(或分支)
因此,我们需要对新值进行完全相同的处理,以找到最大值
从评论中回答您的问题:我不记得为什么我在reduce和rereduce中使用相同的代码,因为那是很久以前的事了(couchbase 2.0在dev preview中的时候)。可能couchbase有一些bug,或者我只是想了解rereduce是如何工作的。但是我记得,如果没有这个if(r){..}
它在那个时候就不起作用了
您可以尝试放置
返回v代码>在my或您的reduce函数的不同部分中编码,以查看它在每个reduce阶段返回的内容。最好自己尝试一次,以了解那里实际发生的情况。我忘了提到我有许多相同密钥的文档。事实上,对于每个密钥,我可以有许多文档(此处的消息):
处理此问题的另一种方法是在map函数中执行此操作:
function (doc, meta) {
var count = 0;
var last =''
if(doc.type =="doc"){
for (k in doc.message){
count += 1;
last = doc.date> last?doc.date:last;
}
emit(doc.key,{'Count':count,'Last': last});
}
}
我发现这很简单,在我的情况下就可以了。你不是在比较日期。。。Couchbase按键对值进行排序。在您的情况下,它不会按日期排序,因此您应该在reduce函数中手动执行。谢谢。我将测试您的代码,但您在REREREDUCE/not REREREDUCE部分使用相同的代码?有什么原因吗?你能解释一下吗?@agstudy我已经更新了我的答案,如果你还有更多问题,尽管问。谢谢你的解释(+1)。我将发布一个与你完全不同的答案。我是couchbase的新手,所以我不确定我是否正确使用了它,所以我需要一些反馈。@agstudy,正如我刚刚写的,尝试放置return v;在reduce函数的不同部分编写代码,以便自己发现它。你也可以阅读这篇文章:这篇文章可能也会很有用。谢谢你的链接。我已经读过了。但我认为它只使用内置的reduce函数。不是吗?
function (doc, meta) {
if(doc.type =="doc")
emit(doc.key, doc.date);
}
function(key, values, rereduce) {
var result = {
Last: 0,
Count: 0
};
if (rereduce) {
for (var i = 0; i < values.length; i++) {
result.Count += values[i].Count;
result.Last = values[i].Last;
}
} else {
result.Count = values.length;
result.Last = values[0]
}
return result;
}
{
"date": "2014-04-16T17:13:00",
"key": "de5cefc56ff51c33351459b88d42ca9f828445c0",
"message": "message1",
}
{
"date": "2014-04-16T15:22:00",
"key": "de5cefc56ff51c33351459b88d42ca9f828445c0",
"message": "message2",
}
function (doc, meta) {
var count = 0;
var last =''
if(doc.type =="doc"){
for (k in doc.message){
count += 1;
last = doc.date> last?doc.date:last;
}
emit(doc.key,{'Count':count,'Last': last});
}
}