You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@couchdb.apache.org by Carl Bourne <ca...@me.com> on 2012/09/20 02:06:29 UTC

Summary view for Pie Charting

Hi,

I'm trying to build a summary view for a pie chart based on a document count within date ranges as shown below. 

The map function is basically working, except I need to get the "emit(XX-Days, 1);" part to write a variable label in the place of the XX-Days. e.g. 30-Days,60-Days,90-Days. However, I can't seem to work out a way to do this. 

Any suggestions would be much appreciated.


Map Function:

function(doc){
    var now = new Date((new Date()).getTime());
    var thirty_days_from_now = new Date((new Date()).getTime() + 30*24*60*60*1000);
    var sixty_days_from_now = new Date((new Date()).getTime() + 60*24*60*60*1000);
    var ninty_days_from_now = new Date((new Date()).getTime() + 90*24*60*60*1000);
    var expire = Date.parse(doc.date.expire)

    
    var exps = [thirty_days_from_now, sixty_days_from_now, ninty_days_from_now];

for (r in exps){
   if (expire >= now && expire <= (exps[r])){
   emit(XX-Days, 1);
     
   }
 }
return;
}

Reduce Function:

_count

Regards,

Carl

Re: Summary view for Pie Charting

Posted by Adam Kocoloski <ko...@apache.org>.
On Sep 20, 2012, at 8:00 AM, Matthieu Rakotojaona <ma...@gmail.com> wrote:

> This raises a question I do not know the answer for : when we use such
> a _list function, are we sure we will not take into account a doc that
> will be added/modified _after_ having launched the function ?

That's correct, it will not.  It grabs an MVCC snapshot of the database when it begins generating the response and uses that same snapshot throughout.

Adam

Re: Summary view for Pie Charting

Posted by Matthieu Rakotojaona <ma...@gmail.com>.
On Thu, Sep 20, 2012 at 1:20 PM, Carl Bourne <ca...@me.com> wrote:
> Thanks,
>
> So I'm assuming the only way to to summarise this information is to do 3 separate queries and aggregate the results?
>
>> It's this;
>>
>> map:
>> function(doc) {
>>  emit(doc.date.expire, null);
>> }
>
> If I query against the above without a reduce (_count) function it returns all documents according to the ?startkey="2012-10-19" and not the count which I need to build the pie chart!
>
> Am I understanding you correctly?
>
> Carl

With this map function, you can query your db like that :

GET /path/to/view?startkey=<now date>&endkey=<now date + 30 days>
GET /path/to/view?startkey=<now date + 30 days>&endkey=<now date + 60 days>
GET /path/to/view?startkey=<now date + 60 days>&endkey=<now date + 90 days>

With a _count as a reduce, you will only get the numbers for each.

You can also use a _list function, if you're okay with couchdb-side
processing (http://wiki.apache.org/couchdb/Formatting_with_Show_and_List)
:

function(head, req) {
  nowDate = req.query.date;
  in30days = new Date();
  in30days.setDate(nowDate.getDate() + 30);

  in60days = new Date();
  in60days.setDate(nowDate.getDate() + 60);

  in60days = new Date();
  in60days.setDate(nowDate.getDate() + 60);

  out["now"] = 0;
  out["in30days"] = 0;
  out[in60days"] = 0;

  while(row = getRow()) {
    if (nowDate <= row.value.expire  && row.value.expire <= in30days) {
      out["now"] += 1;
    } else if (in30days <= row.value.expire  && row.value.expire <= in60days) {
      out["in30days"] += 1;
    } else if (in30days <= row.value.expire  && row.value.expire <= in60days) {
      out["in60days"] += 1;
    }
  }

  send(out["now"] + "-" + out["in30days"] + "-" + out["in60days"]);
}

You would query such a _list with

GET /path/to/_list?date=<date of now>&reduce=false

This raises a question I do not know the answer for : when we use such
a _list function, are we sure we will not take into account a doc that
will be added/modified _after_ having launched the function ?

-- 
Matthieu RAKOTOJAONA

Re: Summary view for Pie Charting

Posted by Carl Bourne <ca...@me.com>.
Thanks,

So I'm assuming the only way to to summarise this information is to do 3 separate queries and aggregate the results?

> It's this;
> 
> map:
> function(doc) {
>  emit(doc.date.expire, null);
> }

If I query against the above without a reduce (_count) function it returns all documents according to the ?startkey="2012-10-19" and not the count which I need to build the pie chart!

Am I understanding you correctly?

Carl



On 20 Sep 2012, at 10:11, Robert Newson <rn...@apache.org> wrote:

> It's this;
> 
> map:
> function(doc) {
>  emit(doc.date.expire, null);
> }
> 
> and there is no reduce function.
> 
> query with ?startkey="today's date minus 30 days encoded in same
> format as doc.date.expire", and same for 60 and 90.
> 
> And remember to ensure that doc.date.expire sorts in the right order.
> Perhaps emit it as new Date(doc.date.expire).getTime() or in ISO-8601
> formatted string.
> 
> B.
> 
> 
> On 20 September 2012 08:04, Carl Bourne <ca...@me.com> wrote:
>> Jens,
>> 
>> Understand!
>> 
>> So I guess then the only way to do this is using 3 separate queries with startkey, endkey for each time period? Then assemble the results externally using whatever performed the query?
>> 
>> Are there any other options?
>> 
>> Regards,
>> 
>> Carl
>> 
>> 
>> On 20 Sep 2012, at 01:18, Jens Alfke <je...@couchbase.com> wrote:
>> 
>>> This isn’t a valid map function, because it’s not purely functional — it uses external input in the form of the current date/time. So if the map function is run twice on the same document, it will not always emit the same output. That’s not allowed.
>>> 
>>> In other words, think of what happens if you generate the index now, and then query it 90 days from now. The information in the index probably won’t be valid because everything will have expired already, right? But CouchDB has no idea the index is time-sensitive, so it’s going to return you the old data anyway. You just cannot put time-sensitive data into a map function.
>>> 
>>> Instead what you should be doing in the map is writing out the expiration times of the documents. Then at query time you can see how far in the future those are.
>>> 
>>> —Jens
>> 


Re: Summary view for Pie Charting

Posted by Robert Newson <rn...@apache.org>.
It's this;

map:
function(doc) {
  emit(doc.date.expire, null);
}

and there is no reduce function.

query with ?startkey="today's date minus 30 days encoded in same
format as doc.date.expire", and same for 60 and 90.

And remember to ensure that doc.date.expire sorts in the right order.
Perhaps emit it as new Date(doc.date.expire).getTime() or in ISO-8601
formatted string.

B.


On 20 September 2012 08:04, Carl Bourne <ca...@me.com> wrote:
> Jens,
>
> Understand!
>
> So I guess then the only way to do this is using 3 separate queries with startkey, endkey for each time period? Then assemble the results externally using whatever performed the query?
>
> Are there any other options?
>
> Regards,
>
> Carl
>
>
> On 20 Sep 2012, at 01:18, Jens Alfke <je...@couchbase.com> wrote:
>
>> This isn’t a valid map function, because it’s not purely functional — it uses external input in the form of the current date/time. So if the map function is run twice on the same document, it will not always emit the same output. That’s not allowed.
>>
>> In other words, think of what happens if you generate the index now, and then query it 90 days from now. The information in the index probably won’t be valid because everything will have expired already, right? But CouchDB has no idea the index is time-sensitive, so it’s going to return you the old data anyway. You just cannot put time-sensitive data into a map function.
>>
>> Instead what you should be doing in the map is writing out the expiration times of the documents. Then at query time you can see how far in the future those are.
>>
>> —Jens
>

Re: Summary view for Pie Charting

Posted by Carl Bourne <ca...@me.com>.
Jens,

Understand! 

So I guess then the only way to do this is using 3 separate queries with startkey, endkey for each time period? Then assemble the results externally using whatever performed the query?

Are there any other options?

Regards,

Carl


On 20 Sep 2012, at 01:18, Jens Alfke <je...@couchbase.com> wrote:

> This isn’t a valid map function, because it’s not purely functional — it uses external input in the form of the current date/time. So if the map function is run twice on the same document, it will not always emit the same output. That’s not allowed.
> 
> In other words, think of what happens if you generate the index now, and then query it 90 days from now. The information in the index probably won’t be valid because everything will have expired already, right? But CouchDB has no idea the index is time-sensitive, so it’s going to return you the old data anyway. You just cannot put time-sensitive data into a map function.
> 
> Instead what you should be doing in the map is writing out the expiration times of the documents. Then at query time you can see how far in the future those are.
> 
> —Jens


Re: Summary view for Pie Charting

Posted by Jens Alfke <je...@couchbase.com>.
This isn’t a valid map function, because it’s not purely functional — it uses external input in the form of the current date/time. So if the map function is run twice on the same document, it will not always emit the same output. That’s not allowed.

In other words, think of what happens if you generate the index now, and then query it 90 days from now. The information in the index probably won’t be valid because everything will have expired already, right? But CouchDB has no idea the index is time-sensitive, so it’s going to return you the old data anyway. You just cannot put time-sensitive data into a map function.

Instead what you should be doing in the map is writing out the expiration times of the documents. Then at query time you can see how far in the future those are.

—Jens