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);
});
}
}