Search code examples
mapreducecouchdbcouchbasenosql-aggregation

How do you sort results of a _View_ by value in the in Couchbase?


So from what I understand in Couchbase is that one can sort keys* by using

descending=true

but in my case I want to sort by values instead. Consider the Twitter data in json format, my question is What it the most popular user mentioned?

Each tweet has the structure of:

{
    "text": "",
    "entities" : {
        "hashtags" : [ ... ],
        "user_mentions" : [ ...],
        "urls" : [ ... ]
}

So having used MongoDB before I reused the Map function and modified it slightly to be usable in Couchbase as follows:

function (doc, meta) {
  if (!doc.entities) { return; }

  doc.entities.user_mentions.forEach(
    function(mention) {
      if (mention.screen_name !== undefined) {
        emit(mention.screen_name, null);
      }
    }
  )
}

And then I used the reduce function _count to count all the screen_name occurrences. Now my problem is How do I sort by the count values, rather than the key?

Thanks


Solution

  • The short answer is you cannot sort by value the result of you view. You can only sort by key.

    Some work around will be to either:

    • analyze the data before inserting them into Couchbase and create a counter for the values you are interested by (mentions in your case)

    • use the view you have to sort on the application size if the size of the view is acceptable for a client side sort.

    The following JS code calls a view, sorts the result, and prints the 10 hottest subjects (hashtags):

    var http =  require('http');
    
    var options = {
        host: '127.0.0.1',
        port: 8092,
        path: '/social/_design/dev_tags/_view/tags?full_set=true&connection_timeout=60000&group=true',
        method: 'GET'
    }
    
    http.request(
        options, 
        function(res) {
            var buf = new Buffer(0);
            res.on('data', function(data) {
                buf += data;
            });
            res.on('end', function() {
                var tweets = JSON.parse(buf);
                var rows = tweets.rows;
                rows.sort( function (a,b){ return b.value - a.value } 
                );
    
    
                for ( var i = 0;  i < 10; i++ ) {
                    console.log( rows[i] );
                }
            });
        }
        ).end();
    

    In the same time I am looking at other options to achieve this