0
votes

I would like to create a view with map / reduce functions that return the latest values from several documents with same id, seems I can return the latest document giving with the xyz id based on the update_datetime, not sure how to get the latest value like field1 and field2, thank you

doc1: id='xyz', field1='v1.0', field2='v2.0', field3='v3.0', status='NEW', update_datetime='2015-04-28'
doc2: id='xyz', field2='v2.1', field3='v3.0', status='CHANGED', update_datetime='2015-05-01'
doc3: id='xyz', field3='v3.1', status='CLOSED', update_datetime='2015-05-10'

define a view with map / reduce that, given a key value 'xyz', returns the following document:

id='xyz', field1='v1.0', field2='v2.1', field3='v3.1', status='CLOSED', update_datetime='2015-05-10'.
1

1 Answers

0
votes

I have a feeling that the data model you have could be improved but I do not know enough about your use case to comment on that really. Therefore I would suggest a reduce function that will perform a merge of the documents using newer as an override for existing properties unless a property does not exist. Here is the content of map and reduce functions (btw, I have changed the name of one of the fields from update_datetime to updated. Also please bear in mind that id and _id are different - might be worth renaming your own id field to something more distinguishable from couchdb's doc id field):

// MAP
function(doc) {
  emit(doc.id, doc);
}
// REDUCE
function(keys, values, rereduce) {
    if (values.length > 1) {
        var mergedDoc = values[0];
        for (var i = 1; i < values.length; i++) {
            var newDoc = values[i];
            var updatingWithNewer = newDoc.updated >= mergedDoc.updated;
            for (key in newDoc) {
                if (key != "_id" && key != "id") {
                    if (updatingWithNewer || mergedDoc[key] == undefined) {
                        mergedDoc[key] = newDoc[key];
                    }
                }
            }
        }
        return mergedDoc;
    } else {
        return values[0];
    }
}

Performing level 1 reduce will give you expected result. Hope it helps.