Considerate
Considerate

Reputation: 417

Get latest item by in group CouchDB view

I have a few documents in CouchDB which contains a date and a path. I want a a view where I can search by path (probably using startkey and endkey) and for that path I want the view to return the document where the date is the latest.

A small example of how my data looks like

{
   "path": "abc",
   "created_at": "2011-12-03T18:23:49.058Z"
}
{
   "path": "abc",
   "created_at": "2011-12-03T11:32:42.123Z"
}
{
   "path": "cde",
   "created_at": "2011-12-06T15:52:34.523Z"
}

My current map function

function(doc) {
  var pathArr = doc.path.split(/\/|\\/);
  pathArr.splice(0,1);

  emit(pathArr, doc); 
}

My attempt to create a reduce function

function(keys, values) {
  var currTime = -Infinity;
  var retDoc;

  for (var i = 0, v; v = values[i]; i++) {
    var dateInMs = new Date(v.created_at).getTime();

    //if this doc has a later than than previously latest date found
    if(dateInMs >= currTime)
    {
       currTime = dateInMs;
       retDoc = v;
    }
  }
  return retDoc;
}

This results in the error

{"error":"reduce_overflow_error","message":"Reduce output must shrink more rapidly: Current output: ..."}

I've read in the Definitive Guide that the error occurs because you're not supposed to return a full document from a reduce function. Is there any other way to solve this?

I appreciate all help I can get.

EDIT:

I just thought of the ugly solution to let the reduce function to return the _id of the document and then through a second request fetch the document. What do you think of this solution? If you can find a good solution for this instead I would be very happy.

Upvotes: 0

Views: 1013

Answers (1)

Considerate
Considerate

Reputation: 417

I found a solution to this, I thought it would be nice to post it here if someone ended up in a similar situation.

The solution was quite simple actually, I just added the pathArray as a nested array to the key. That way I made it possible to query the path for a file and only get the latest version.

This is my new map function:

function(doc) {
  if(doc.doctype === "file")
  {
    var pathArr = doc.guipath.split(/\/|\\/);
    pathArr.splice(0,1);

    emit([pathArr,doc.created_at], doc);
  }
}

And I don't use a reduce function.

I query this view by adding the following (or similar) parameters:

?startkey=[["haha","file.ext"],{}]&endkey=[["haha","file.ext"]]&descending=true&limit=1

This way I can be sure that I'm only getting the latest one.

Upvotes: 3

Related Questions