使用CouchDB视图时,我可以同时计算组并按键范围进行过滤吗? [英] Using a CouchDB view, can I count groups and filter by key range at the same time?
问题描述
我正在使用CouchDB.我希望能够计算可在查询时指定的日期范围内特定字段的值的出现次数.我似乎可以做到这一点,但我无法理解将其整合在一起的最佳方法.
I'm using CouchDB. I'd like to be able to count occurrences of values of specific fields within a date range that can be specified at query time. I seem to be able to do parts of this, but I'm having trouble understanding the best way to pull it all together.
假设文档具有一个时间戳字段和另一个字段,例如:
Assuming documents that have a timestamp field and another field, e.g.:
{ 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/all-docs?startkey=20120101-0000&endkey=20120201-0000
.
I can easily create a view that filters documents by a flexible date range. This can be done with a view like the one below, called with key range parameters, e.g. _view/all-docs?startkey=20120101-0000&endkey=20120201-0000
.
all-docs/map.js:
function(doc) {
emit(doc.date, doc);
}
使用上面的数据,这将返回一个仅包含前4个文档(日期范围内唯一的文档)的CouchDB视图.
With the data above, this would return a CouchDB view containing just the first 4 docs (the only docs in the date range).
我还可以创建一个查询,该查询计算给定字段的出现次数,像这样,通过分组调用,即_view/author-count?group=true
:
I can also create a query that counts occurrences of a given field, like this, called with grouping, i.e. _view/author-count?group=true
:
author-count/map.js:
function(doc) {
emit(doc.author, 1);
}
author-count/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
并得到这样的结果,其中最后一个文档被排除在计数之外,因为它不在指定的日期范围内:>
However, I can't find the best way to both filter by date and count occurrences. For example, with the data above, I'd like to be able to specify range parameters like startkey=20120101-0000&endkey=20120201-0000
and get a result like this, where the last doc is excluded from the count because it is outside the specified date range:
{
"rows": [
{"key":"bart","value":1},
{"key":"homer","value":2}
{"key":"lisa","value":1}
]
}
最优雅的方法是什么?一个查询就能做到吗?我应该使用另一个CouchDB构造还是一个足够的视图呢?
What's the most elegant way to do this? Is this achievable with a single query? Should I be using another CouchDB construct, or is a view sufficient for this?
推荐答案
您可以使用列表非常接近所需的结果:
You can get pretty close to the desired result with a list:
{
_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慢,并且有些变通办法.不幸的是,这是进行多维查询的唯一方法,哪个CouchDB不适合" .
This will be slower than a normal map-reduce, and is a bit of a workaround. Unfortunately, this is the only way to do a multi-dimensional query, "which CouchDB isn’t suited for".
请求此设计的结果将是这样的:
The result of requesting this design will be something like this:
{
"bart": 1,
"homer": 2,
"lisa": 2
}
我们所做的基本上是发出很多元素,然后根据需要使用列表对它们进行分组.列表可用于以任何您想要的方式显示结果,但通常也较慢.可以缓存普通的map-reduce,仅根据差异进行更改,而每次请求时,都必须重新构建列表.
What we do is basically emit a lot of elements, then using a list to group them as we want. A list can be used to display a result in any way you want, but will also often be slower. Whereas a normal map-reduce can be cached and only change according to the diffs, the list will have to be built anew every time it is requested.
这几乎和获取地图中所有元素的速度一样慢(编排数据的开销几乎可以忽略):比获取reduce的结果要慢得多.
It is pretty much as slow as getting all the elements resulting from the map (the overhead of orchestrating the data is mostly negligible): a lot slower than getting the result of a reduce.
如果要将列表用于其他视图,则只需在您请求的URL中进行交换即可:
If you want to use the list for a different view, you can simply exchange it in the URL you request:
http://<couchurl>/<db>/_design/authors/_list/count_occurrences/<view>
了解有关列表上的更多信息.
这篇关于使用CouchDB视图时,我可以同时计算组并按键范围进行过滤吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!