You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@couchdb.apache.org by Sho Fukamachi <sh...@gmail.com> on 2008/11/09 22:36:46 UTC

dual purpose filter/count views

Hi all,

This is probably a really simple question, but for some reason* I  
can't figure it out.

(* reason is most like extreme dumbness on my part)

I've got a bunch of views where i have something like this:

get_all_by_field:

map: if (doc.type == 'my_doc') emit(doc.field, doc);

count_all_by_field:

map: if (doc.type == 'my_doc') emit(doc.field, 1);
reduce: function(keys, values) { return sum(values) }

That works fine, but seems like it could be more elegant ..

I thought I'd be "clever" and try to combine the two, so I could get  
the "search" output by calling the map alone, and then getting the  
count by turning on reduce, something like this:

map: function(doc) {
   if (doc.type == 'my_doc') emit(doc.field, [doc, 1]);
     }
reduce: function(keys, values) { return sum(values[1]) }

The idea being that if i turn off reduce, it outputs the docs I want,  
but if I turn it on, I can just count the second element in the  
emitted array.

But for some reason it doesn't work. I've tried the above, just  
returning values[1], trying to sum values[0][1], etc. I either get  
errors or nothing.

This is probably some really simple thing that I'm missing in my tired  
state. Can anyone give me a hint as to what it is? : )

thanks!

Sho

Re: dual purpose filter/count views

Posted by Antony Blakey <an...@gmail.com>.
On 10/11/2008, at 8:06 AM, Sho Fukamachi wrote:

> Hi all,
>
> This is probably a really simple question, but for some reason* I  
> can't figure it out.
>
> (* reason is most like extreme dumbness on my part)
>
> I've got a bunch of views where i have something like this:
>
> get_all_by_field:
>
> map: if (doc.type == 'my_doc') emit(doc.field, doc);
>
> count_all_by_field:
>
> map: if (doc.type == 'my_doc') emit(doc.field, 1);
> reduce: function(keys, values) { return sum(values) }
>
> That works fine, but seems like it could be more elegant ..
>
> I thought I'd be "clever" and try to combine the two, so I could get  
> the "search" output by calling the map alone, and then getting the  
> count by turning on reduce, something like this:
>
> map: function(doc) {
>  if (doc.type == 'my_doc') emit(doc.field, [doc, 1]);
>    }
> reduce: function(keys, values) { return sum(values[1]) }

In any case, this isn't valid logic - you need to do something like

theSum = 0;
for (var i in values)
   theSum = theSum + values[i][1];
return theSum;

Antony Blakey
--------------------------
CTO, Linkuistics Pty Ltd
Ph: 0438 840 787

What can be done with fewer [assumptions] is done in vain with more
   -- William of Ockham (ca. 1285-1349)




Re: dual purpose filter/count views

Posted by Antony Blakey <an...@gmail.com>.
On 10/11/2008, at 8:06 AM, Sho Fukamachi wrote:

> This is probably some really simple thing that I'm missing in my  
> tired state. Can anyone give me a hint as to what it is? : )

The reduce function takes a third parameter, which is false when the  
input to the reduce function is output from your map function, and  
true when the input to the reduce function is output from previous  
invocations of the reduce function. In your case you could do  
something like this:

   reduce: function(keys, values, rereduce) { if (rereduce) return  
sum(values) else return sum(values[1]) }

When doing a re-reduce, keys will also be null.

Antony Blakey
-------------
CTO, Linkuistics Pty Ltd
Ph: 0438 840 787

On the other side, you have the customer and/or user, and they tend to  
do what we call "automating the pain." They say, "What is it we're  
doing now? How would that look if we automated it?" Whereas, what the  
design process should properly be is one of saying, "What are the  
goals we're trying to accomplish and how can we get rid of all this  
task crap?"
   -- Alan Cooper



Re: dual purpose filter/count views

Posted by Sho Fukamachi <sh...@gmail.com>.
On 10/11/2008, at 9:01 AM, Chris Anderson wrote:

> Reduce:
>
> function(keys, values, rereduce) {
>  if (rereduce) {
>    return sum(values);
>  } else {
>    return values.length;
>  }
> }

Cool idea, works nicely in this situation and very elegant. Thanks for  
the tip!

Sho

> -- 
> Chris Anderson
> http://jchris.mfdz.com


Re: dual purpose filter/count views

Posted by Chris Anderson <jc...@apache.org>.
On Sun, Nov 9, 2008 at 1:36 PM, Sho Fukamachi <sh...@gmail.com> wrote:


> map: function(doc) {
>  if (doc.type == 'my_doc') emit(doc.field, [doc, 1]);
>    }
> reduce: function(keys, values) { return sum(values[1]) }

Anthony's second email has a working idea, but this is how I like to
do it. Will work for any map function, so you can drop the funny array
value from your map.

Reduce:

function(keys, values, rereduce) {
  if (rereduce) {
    return sum(values);
  } else {
    return values.length;
  }
}





-- 
Chris Anderson
http://jchris.mfdz.com