开发者

Couchdb: filter and group in a single view

开发者 https://www.devze.com 2023-02-01 07:56 出处:网络
I have a Couchdb database with documents of the form: { Name, Timestamp, Value } I have a view that shows a summary grouped by name with the sum of the values.This is straigh开发者_如何学Ct forward r

I have a Couchdb database with documents of the form: { Name, Timestamp, Value }

I have a view that shows a summary grouped by name with the sum of the values. This is straigh开发者_如何学Ct forward reduce function.

Now I want to filter the view to only take into account documents where the timestamp occured in a given range.

AFAIK this means I have to include the timestamp in the emitted key of the map function, eg. emit([doc.Timestamp, doc.Name], doc)

But as soon as I do that the reduce function no longer sees the rows grouped together to calculate the sum. If I put the name first I can group at level 1 only, but how to I filter at level 2?

Is there a way to do this?


I don't think this is possible with only one HTTP fetch and/or without additional logic in your own code.

If you emit([time, name]) you would be able to query startkey=[timeA]&endkey=[timeB]&group_level=2 to get items between timeA and timeB grouped where their timestamp and name were identical. You could then post-process this to add up whenever the names matched, but the initial result set might be larger than you want to handle.

An alternative would be to emit([name,time]). Then you could first query with group_level=1 to get a list of names [if your application doesn't already know what they'll be]. Then for each one of those you would query startkey=[nameN]&endkey=[nameN,{}]&group_level=2 to get the summary for each name.

(Note that in my query examples I've left the JSON start/end keys unencoded, so as to make them more human readable, but you'll need to apply your language's equivalent of JavaScript's encodeURIComponent on them in actual use.)


You can not make a view onto a view. You need to write another map-reduce view that has the filtering and makes the grouping in the end. Something like:

map:
function(doc) {
  if (doc.timestamp > start and doc.timestamp < end ) {
    emit(doc.name, doc.value);
  }
}

reduce:
function(key, values, rereduce) {
  return sum(values);
}

I suppose you can not store this view, and have to put it as an ad-hoc query in your application.

0

精彩评论

暂无评论...
验证码 换一张
取 消