Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Count documents of certain type (filter against user before)

Documents (pseudo, rev and id omitted):

{
   "type": 1,
   "username": "aron",
   "data": { ... }
}
{
   "type": 1,
   "username": "bob",
   "data": { ... }
}
{
   "type": 1,
   "username": "steve",
   "data": { ... }
}
{
   "type": 1,
   "username": "steve",
   "data": { ... }
}
{
   "type": 2,
   "username": "steve",
   "data": { ... }
}
{
   "type": 3,
   "username": "steve",
   "data": { ... }
}
{
   "type": 3,
   "username": "steve",
   "data": { ... }
}
{
   "type": 3,
   "username": "steve",
   "data": { ... }
}

I want to know, how many documents of type 1/2/3 steve has.

View:

count: {
    map: function (doc) { 
        emit([doc.username, doc.type], 1);  
    }
    reduce: function (key, values, rereduce) {
        return sum(values);
    }
}

Now I request

/database/_design/myDesign/_view/count?key=["steve",1] // result: 2
/database/_design/myDesign/_view/count?key=["steve",2] // result: 1
/database/_design/myDesign/_view/count?key=["steve",3] // result: 3

This works perfectly well.

To smart things up, I was wondering if I can query that in one view?

Is there a way to count the number of documents of unknown number of types in one view?

like image 802
Aron Woost Avatar asked Oct 17 '25 12:10

Aron Woost


2 Answers

You can POST to your view with a body like this;

{"keys":[["steve",1], ["steve",2]]}

Also, try using "_sum" as your reduce function, it will run natively in Erlang and should be several times faster than doing it in Javascript.

like image 145
Robert Newson Avatar answered Oct 21 '25 01:10

Robert Newson


You can perform a range query to achieve this:

.../count?startkey=["steve",1]&endkey=["steve",3]&group=true&reduce=true

This will fetch one line for every key between ["steve",1] and ["steve",3] inclusive. You can adjust values 0 and 3 according to what your types can actually be. For instance, if your types can be any scalar value, you can use ["steve",null] and ["steve",{}] as the range boundaries.

like image 23
Victor Nicollet Avatar answered Oct 20 '25 23:10

Victor Nicollet