Mapreduce 按日期范围和类型列出的CouchDB总和

Mapreduce 按日期范围和类型列出的CouchDB总和,mapreduce,couchdb,Mapreduce,Couchdb,简单地说,我想按类型对日期范围内的总数进行分组。数据库中的原始文档都是针对单个日期的,包含类型的数据。(例如,每个文档都有在某个日期采摘的苹果、桔子和梨的总数。我们要查询在某个日期范围内采摘的苹果、桔子和梨的总数。) “myview”地图发出 emit([date,type],value\u数组) 我可以按以下方式查询日期范围: …\u view/myview?group=true&group\u level=2&startkey=[20150501]&endkey=[20150530,{}]

简单地说,我想按类型对日期范围内的
总数进行分组。数据库中的原始文档都是针对单个日期的,包含类型的数据。(例如,每个文档都有在某个日期采摘的苹果、桔子和梨的总数。我们要查询在某个日期范围内采摘的苹果、桔子和梨的总数。)

“myview”地图发出

emit([date,type],value\u数组)

我可以按以下方式查询日期范围:

…\u view/myview?group=true&group\u level=2&startkey=[20150501]&endkey=[20150530,{}]

问题就在这里。它可以为
group_level=1
中的每个日期提供一个总和,但我想忘记当时的日期。我想以某种方式重新输入类型,然后求和

我想我需要两个连续的观点,但不知道如何做到这一点

试试这个映射功能

emit([类型,日期],值\u数组)

钥匙的顺序很重要。如果您希望对查询结果进行分组,那么您希望以“变化最少到变化最多”的顺序发出键。也就是说,在文档中首先发出对组更改最少的键。然后是比上一个改变更多的键,依此类推。例如,上面的emit函数应该将输出返回为

["type1",20150501],val of the keys
["type1",20150502],val of the keys
["type1",20150503],val of the keys
["type2",20150502],val of the keys
请注意,“type1”在三个结果中是相同的,日期变化最大。现在,如果在视图上执行
?group_level=1
,您将得到如下结果

["type1"],val of the keys
这是按“type1”分组的所有键。如果执行
?group_level=2
,您将获得按“type1”和日期键分组的所有键。这意味着,如果第一个键和第二个键相等,它们将被分组在一起


couchdb中的分组从左到右进行。首先检查最左侧的关键点以查看它们是否相等,然后检查下一个关键点,依此类推。所有相等的键都分组在一起

我使用视图上的列表功能来完成这项工作。以下是概述:

  • 视图处理日期范围的选择(按日期键入并使用
    ../myview?startkey=20150101&endkey=20150130
  • 列表中有一些按类型分组的Javascript(作为奖励,您还可以排序)
My List函数如下所示(基于按类型分组javascript数组):

先前的视图应该
发出日期作为键,javascript对象作为值。在本例中,视图的一行应该如下所示:
“key”:20150101,“value”:{“type”:“apple”,“value1”:28,“value2”:0}
。如果您是coach新手,下面是如何编写
map
函数的(无论你多么想
\u sum
,也不要使用reduce):

最后,您的查询如下所示:

http://localhost:5984/dbname/_design/ddocname/_list/mylistname/myviewname?startkey=20150501&endkey=20150510


我对Javascript和Coach都有点陌生,所以请随意尝试一下这段代码。

都是真的,但我认为CouchDB无法从第二个键中选择日期范围。我不知何故需要排除的日期在“按类型减少”之前完全不显示。你的意思是想根据类型和日期范围进行筛选,但按类型分组。如果是这样,你可以可以通过开始键和结束键参数排除键。就像您在问题中所做的那样。
startkey=[“type1”,开始日期范围]&endkey=[“type1”,结束日期范围]&reduce=true&group_level=1
。或者你在寻找其他东西吗?是的,但适用于所有类型。我理解为什么CouchDB不能这样做,因为它只选择连续的范围。请参阅Coach db用户邮件列表。这家伙暗示你可以使用“第二视图”来完成此操作。我之所以对此投赞成票,是因为它清楚地说明了在索引范围内按类型分组时遇到的问题。谢谢。很高兴您发现它很有用:)我忘记了列表!如果您使用的是列表函数,那么就没有必要发出这么大的值。只需使用一个
include\u docs=true
参数。这是一个类似于
emit(doc.date)的emit
使用
include_docs=true查询
将获得相同的结果,并具有更小的视图索引的额外优势。文档将在
行[index]中访问。doc
。使用
日志()
在控制台上打印内容以帮助您进行调试。希望有帮助:)
function (head, req){
         var row;
         var rows = [];
         while(row = getRow()){
                rows.push({
                    "type": row.value.type,
                    "value1": row.value.value1,
                    "value2": row.value.value2      
                });
         };


        var result = rows.reduce(function(res, obj) {
                if (!(obj.type in res)){
                    res.__array.push(res[obj.type] = obj);
                } else {
                    res[obj.symbol].value1 += obj.value1;
                    res[obj.symbol].value2 += obj.value2;
                }
                return res; 
                }, 
                {__array:[]}).__array;

        send(toJSON(result));
    }
function(doc){
    if (doc.type === "mydoctype"){
        // build array for the day
        var items = [];
        doc.items.forEach(function(item){
            items.push({
                    'type': item.type,
                    'value1': +item.value1,
                    'value2': +item.value2
                   });
             });

        items.forEach(function(item){
            // convert text date "yyyy-mm-dd"
            var x = doc.date.split('-');
            // to numerical date YYYYMMDD
            newformatdate = +(x[0]+x[1]+x[2]);

            emit(newformatdate, item);
        });
    }
}