Hello, I am hoping the group can provide some guidance on building a
map/reduce summary for a set of documents that I have retrieved with a
complex key range query.
In summary, I want to query a range of docs by a complex key
consisting of an [id, year, month, day, engine]. It is common for me
to need to query over a range of dates with something along the lines
of this (CouchRest Ruby code):
sd = SearchDocument.by_ad_domain_histogram(:startkey => [3, 2009,
9, 1, "g"], :endkey => [3, 2009, 9, 28, "g"], :include_docs =>
false, :reduce => true)
In this example, I want all SearchDocuments that are for category '3'
between 9/1/2009 and 9/28/2009, and for engine 'g'.
Now, this is working well and returning a range of docs. So the
tricky part (at least for me as a CouchDB n00b) is that each of these
docs also has an 'ad_domain' value. And what I want is to generate a
simple histogram which groups all of these range of docs by the
ad_domains found. So I want to get back at the end of the day is
something like:
{'foo.com' => 12, 'bar.com' => 32, 'baz.com' => 14}
This is what I am stuck on as I have not wrapped my head around map/
reduce in CouchDB quite yet. I think this would be easier if I
emitted the ad_domain at the end of the complex key if ALL of the
parts of the key that I was querying on were the same. But since I am
querying on a range of keys I end up with a reduce spitting out
multiple entries for 'foo.com' since that domain was found across
several days (unique complex keys) of results.
Is it possible to do what I want?
Here is a work in progress map/reduce, which doesn't do what I want
yet. Help in modifying it would be much appreciated (and tips for
doing what I am already doing, only better!):
view_by :ad_domain_histogram,
:map =>
'function(doc) {
if( (doc["couchrest-type"] == "SearchDocument") &&
doc.category_id && doc.searched_at && doc.engine) {
var domain;
if(doc.ad_domain == null){
domain="NONE";
}else{
domain=doc.ad_domain;
}
emit([doc.category_id,
new Date(Date.parse(doc.searched_at)).getFullYear(),
new Date(Date.parse(doc.searched_at)).getMonth() + 1,
new Date(Date.parse(doc.searched_at)).getDate(),
doc.engine],
domain);
}
}',
:reduce =>
"function(keys, values, rereduce) {
return sum(values);
}"
Thanks very much in advance,
Glenn