Filtering and Ordering CouchDB View Results

January 22, 2009

Being able to map documents to (key, value) pairs is really useful, but the views I installed in my previous post return all pairs in no particular order. What if I only want the titles of articles posted in December 2007?

Last time I mentioned in passing that you can emit keys as part of the map method. Keys are how CouchDB orders and filters result sets. The view collation specification has the full details on how keys are sorted. To order and filter documents by posting date, I just need to emit doc.posted_at as the key in my map function.

// Get all article titles ordered by posted date.
function(doc) {
  if(doc.type == 'article') {
    emit([doc.posted_at], doc.title);
  }
}

You'll notice I always wrap my keys in arrays. That's a personal preference — it made it easier to get my branch of ActiveCouch to support multiple keys consistently.

A typical result set from this map looks like this:

// GET /blog/_articles/titles_by_posted_at
{
"total_rows":75,
"offset":0,
"rows":[
  {"id":"showing-multiple-message-types-with-the-flash","key":["2007-12-15T20:14:02Z"],"value":"Showing multiple message types with the flash"},
  {"id":"class-instance-and-singleton-methods","key":["2007-12-20T14:50:41Z"],"value":"Class, Instance and Singleton methods"},
  // ... and so on ...
}

See how the articles come back sorted by date? Lower dates appear earlier in the results. That's the key doing its job.

You can also use the key to pick out specific articles. Want just the article published at 2007-12-20T14:50:41Z? Ask for that exact key:

// GET /blog/_articles/titles_by_posted_at?key=["2007-12-20T14:50:41Z"]

{"total_rows":75,"offset":0,"rows":[
{"id":"class-instance-and-singleton-methods","key":["2007-12-20T20:50:41Z"],"value":"Class, Instance and Singleton methods"}
]}

Need a range of results? Specify a startkey and endkey and CouchDB returns everything in between. Since keys are compared as strings, you can use slightly nonsensical times like 24:00 to make sure you capture everything within your target window:

// GET /blog/_view/articles/titles_by_created_at?startkey=[%222007-12-01T00:00:00Z%22]&endkey=[%222007-12-31T24:00:00Z%22]

{"total_rows":75,"offset":0,"rows":[
{"id":"showing-multiple-message-types-with-the-flash","key":["2007-12-15T20:14:02Z"],"value":"Showing multiple message types with the flash"},
{"id":"class-instance-and-singleton-methods","key":["2007-12-20T14:50:41Z"],"value":"Class, Instance and Singleton methods"}
]}

key, startkey, and endkey are just three of the parameters available in CouchDB's view API. There's a whole bunch more documented at the CouchDB HTTP View API reference.

Questions or thoughts? Get in touch.