CouchDB 按日期范围和类型求和
CouchDB sum by date range and type
简单地说,我想 _sum
日期范围 的总计,按 类型 分组。数据库中的原始文档每个都是一个日期,包含 类型 的数据。 (例如,每个文档都有在某个日期采摘的苹果、橙子和梨的总数。我们要查询在某个日期范围内采摘的苹果、橙子和梨的总数。)
"myview"图发
emit([date, type], values_array);
我可以查询日期范围
..._view/myview?group=true&group_level=2&startkey=[20150501]&endkey=[20150530,{}]
问题就在这里。它可以在 group_level=1
给出每个日期的总和,但我想忘记当时的日期。我想以某种方式重新键入 type 然后求和。
我想为此我需要连续使用两个视图,但不确定该怎么做。
试试这个地图功能
emit([type,date], values_array);
键的顺序很重要。如果您想对查询结果进行分组,那么您希望以 "least changing to most changing" 顺序发出您的密钥。那就是发出文档中的密钥,这将首先对一组更改最少。然后将比前一个变化更多的键,依此类推。例如上面的 emit 函数应该 return 输出为
["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 按类型分组。 (作为奖励,您还可以排序)。
我的 List 函数如下所示(基于 this Q&A 关于按类型对 javascript 数组进行分组的内容):
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));
}
之前的View应该emit
日期作为键,javascript对象作为值。在此示例中,视图的一行应如下所示:"key":20150101, "value":{"type":"apple", "value1":28, "value2":0}
。如果您是 Couch 的新手,这里是您编写 map
函数的方式(不要使用 reduce,但是您可能很想 _sum
):
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);
});
}
}
最后,您的查询如下所示:
http://localhost:5984/dbname/_design/ddocname/_list/mylistname/myviewname?startkey=20150501&endkey=20150510
我对 Javascript 和 Couch 都不熟悉,所以请随意尝试一下这段代码。
简单地说,我想 _sum
日期范围 的总计,按 类型 分组。数据库中的原始文档每个都是一个日期,包含 类型 的数据。 (例如,每个文档都有在某个日期采摘的苹果、橙子和梨的总数。我们要查询在某个日期范围内采摘的苹果、橙子和梨的总数。)
"myview"图发
emit([date, type], values_array);
我可以查询日期范围
..._view/myview?group=true&group_level=2&startkey=[20150501]&endkey=[20150530,{}]
问题就在这里。它可以在 group_level=1
给出每个日期的总和,但我想忘记当时的日期。我想以某种方式重新键入 type 然后求和。
我想为此我需要连续使用两个视图,但不确定该怎么做。
试试这个地图功能
emit([type,date], values_array);
键的顺序很重要。如果您想对查询结果进行分组,那么您希望以 "least changing to most changing" 顺序发出您的密钥。那就是发出文档中的密钥,这将首先对一组更改最少。然后将比前一个变化更多的键,依此类推。例如上面的 emit 函数应该 return 输出为
["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 按类型分组。 (作为奖励,您还可以排序)。
我的 List 函数如下所示(基于 this Q&A 关于按类型对 javascript 数组进行分组的内容):
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));
}
之前的View应该emit
日期作为键,javascript对象作为值。在此示例中,视图的一行应如下所示:"key":20150101, "value":{"type":"apple", "value1":28, "value2":0}
。如果您是 Couch 的新手,这里是您编写 map
函数的方式(不要使用 reduce,但是您可能很想 _sum
):
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);
});
}
}
最后,您的查询如下所示:
http://localhost:5984/dbname/_design/ddocname/_list/mylistname/myviewname?startkey=20150501&endkey=20150510
我对 Javascript 和 Couch 都不熟悉,所以请随意尝试一下这段代码。