2

I have a couchdb database filled with time-stamped documents so the format of a given document is something like this:

{ id: "uniqueid",
  year: 2011,
  month: 3,
  day: 31,
  foo: "whatever"
  bar: "something else"
}

I would like to construct a set of views such that a given key will return an array of year, month or day values for which documents exist. For example given the view name Days, I would like the following view url

/db/_design/designdoc/_view/Days?key=[2011,3]

to return an array of all the days in March of 2011 for which documents exist. For example, if March 2011 had some number of documents falling on six days, it might look like:

[1, 2, 5, 15, 27, 31]

Similarly,

/db/_design/designdoc/_view/Months?key=2011

If 2011 had some number of documents falling on April, May, and September, it might look like:

[4, 5, 9]

And

/db/_design/designdoc/_view/Years

will return an array of years in the whole database. If the documents have this year and last, it might look like:

[2010, 2011]

I gather it is difficult to write a reduce function that returns an array because you end up running into reduce overflow errors as the document count increases. I know this because I wrote a reduce function that worked but then started throwing reduce overflow errors after I loaded it up with documents.

One solution I have examined is just creating a view without a reduce that creates an array key [year, month, day] and then using startkey and endkey parameters on the view to return documents. The problem with this approach is how it scales. Say my database has thousands of documents spread out over two years. Using this view, I need to iterate over the entire set of documents just to discover this.

I believe this question is trying to ask the same thing though I am not quite sure so I figured I'd add a new question. Also, the answers given on that question do not avoid reduce overflow errors for larger document sets, as far as I could tell with my limited view writing skills.

4
  • My answer to this question was broken. I'm sorry. I have updated it, please have another look. Commented Apr 3, 2011 at 11:58
  • I am trying to understand your question. I edited it to show the expected output. Is my understanding correct? If so, I'll write up an answer. Thanks. Commented Apr 4, 2011 at 5:23
  • @jhs, yes this is correct. Thanks for making it more clear. Commented Apr 4, 2011 at 6:17
  • @jhs: Any further ideas about this? I'm still stumped. Commented Apr 25, 2011 at 21:42

2 Answers 2

1

I think for this, ou need to construct your views not only with maps, but also with reduces.

Sign up to request clarification or add additional context in comments.

Comments

0

Disregarding eventual scaling problems there are 2 solutions. I will take into account only Days since the answer for Months and Years is similar.

Solution 1:

view Days:

map:

function(doc) {
    if (doc.year && doc. month && doc.day) {
        emit([ year, month, day ], 1);
    }
}

reduce:

function(keys, values) {
    return sum(values);
}

list listDays:

function(head, req) {
    start({
        "headers": {
            "Content-Type": "text/plain"
        }
    });
    var row;
    var days = new Array();
    while(row = getRow()) {
        days.push(row.key[2]);
    }
    var daysString = json.join(',');
    send('[' + daysString + ']');
}

http call:

http://couch/db/_design/db/_list/listDays/Days?group=true&group_level=2&startkey=["2011","3"]&endkey=["2011","3Z"]

Solution 2:

view Days:

map:

function(doc) {
    if (doc.year && doc. month && doc.day) {
        emit([ year, month, day ], null);
    }
}

list listDays:

function(head, req) {
    start({
        "headers": {
            "Content-Type": "text/plain"
        }
    });
    var row;
    var days = new Array();
    while(row = getRow()) {
        if (days.indexOf(row.key[2] == -1) { days.push(row.key[2]); }
    }
    var daysString = json.join(',');
    send('[' + daysString + ']');
}

http call:

http://couch/db/_design/db/_list/listDays/Days?startkey=["2011","3"]&endkey=["2011","3Z"]

2 Comments

Thanks! I'll have a look at this and let you know how it works out.
Please note that I wrote the code in "free style". I hope there are no errors :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.