我正在使用 CouchDB。我希望能够计算可以在查询时指定的日期范围内特定字段值的出现次数。我似乎能够完成其中的一部分,但我无法理解将它们整合在一起的最佳方式。
假设文档具有时间戳字段和另一个字段,例如:
{ date: '20120101-1853', author: 'bart' }
{ date: '20120102-1850', author: 'homer'}
{ date: '20120103-2359', author: 'homer'}
{ date: '20120104-1200', author: 'lisa'}
{ date: '20120815-1250', author: 'lisa'}
我可以轻松创建一个 View 按灵活的日期范围过滤文档 .这可以通过像下面这样的 View 来完成,用关键范围参数调用,例如
_view/all-docs?startkey=20120101-0000&endkey=20120201-0000
.所有文档/map.js:
function(doc) {
emit(doc.date, doc);
}
使用上面的数据,这将返回一个只包含前 4 个文档(日期范围内唯一的文档)的 CouchDB View 。
我还可以创建一个查询 计算给定字段的出现次数 ,像这样,用分组调用,即
_view/author-count?group=true
:作者计数/map.js:
function(doc) {
emit(doc.author, 1);
}
作者计数/reduce.js:
function(keys, values, rereduce) {
return sum(values);
}
这会产生类似的结果:
{
"rows": [
{"key":"bart","value":1},
{"key":"homer","value":2}
{"key":"lisa","value":2}
]
}
但是,我找不到 的最佳方式按日期过滤并计算出现次数 .例如,使用上面的数据,我希望能够指定范围参数,如
startkey=20120101-0000&endkey=20120201-0000
并得到这样的结果,其中最后一个文档被排除在计数之外,因为它在指定的日期范围之外:{
"rows": [
{"key":"bart","value":1},
{"key":"homer","value":2}
{"key":"lisa","value":1}
]
}
什么是最优雅的方式来做到这一点?这可以通过单个查询实现吗?我应该使用另一个 CouchDB 构造,还是一个 View 就足够了?
最佳答案
您可以使用列表非常接近所需的结果:
{
_id: "_design/authors",
views: {
authors_by_date: {
map: function(doc) {
emit(doc.date, doc.author);
}
}
},
lists: {
count_occurrences: function(head, req) {
start({ headers: { "Content-Type": "application/json" }});
var result = {};
var row;
while(row = getRow()) {
var val = row.value;
if(result[val]) result[val]++;
else result[val] = 1;
}
return result;
}
}
}
这种设计可以这样要求:
http://<couchurl>/<db>/_design/authors/_list/count_occurrences/authors_by_date?startkey=<startDate>&endkey=<endDate>
这将比普通的 map-reduce 慢,并且是一种解决方法。不幸的是,这是进行多维查询的唯一方法,"which CouchDB isn’t suited for" .
请求此设计的结果将是这样的:
{
"bart": 1,
"homer": 2,
"lisa": 2
}
我们所做的基本上是发出很多元素,然后根据需要使用列表对它们进行分组。列表可用于以您想要的任何方式显示结果,但通常也会较慢。而普通的 map-reduce 可以被缓存,并且只能根据差异进行更改,但每次请求时都必须重新构建列表。
它几乎与获取从映射产生的所有元素一样慢(编排数据的开销几乎可以忽略不计):比获取减少的结果慢得多。
如果您想将列表用于不同的 View ,只需在您请求的 URL 中交换它:
http://<couchurl>/<db>/_design/authors/_list/count_occurrences/<view>
阅读更多关于 lists on the couchdb wiki .
关于mapreduce - 使用 CouchDB View ,我可以同时计算组数并按键范围过滤吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12944294/