Search code examples
mongodbmongodb-javagmongo

gmongo MapReducer with Finalizer


I do not know how to set Finalizer when using gmongo. My 'reduce' contains an Array that I want to use in 'Finalize'

Map and Reduce are as shown below

String map="""
  function map(){
  key = this.vendor
  var inSec=Math.round(this.timeTook/1000*100)/100
  value= {response_time:[inSec]}
  emit(key, value)
}
"""
String reduce = """
    function reduce(key,values){
      var call_list={response_time:[]}
      var count = 0
      var total=0
      for (var i in values){
        call_list.response_time=values[i].response_time.concat(call_list.response_time)
      }
      call_list.response_time= call_list.response_time.sort(function(a,b){return a-b})
      return call_list
    }
"""
        String collection="mapreduceresult"

When I invoke mapreduce as below, I get an error - query too large

            MapReduceCommand cmd = new MapReduceCommand(logCollection, map,reduce,null,MapReduceCommand.OutputType.MERGE,null)
            cmd.setOutputDB(collection)
            cmd.setFinalize(finalizer) //- wanted to use Finalize as the reducer returns an Array
            logCollection.mapReduce(cmd) //This is giving an error - Query is too large..

Only this is working for me but do not know how to set Finalize

   logCollection.mapReduce(map,reduce,collection,[:])

Solution

  • take a look at this working example, the finalize function is just converting the number to a String:

    @Grab(group='com.gmongo', module='gmongo', version='1.2')
    import com.gmongo.GMongo
    import com.mongodb.MapReduceCommand
    import com.mongodb.BasicDBObject
    
    def mongo = new GMongo()
    def db = mongo.getDB("gmongo")
    
    def words = ['foo', 'bar', 'baz']
    def rand  = new Random()        
    
    db.words.drop()
    
    1000.times { 
        db.words << [word: words[rand.nextInt(3)]]
    }
    
    assert db.words.count() == 1000
    
    def map = """
        function map() {
            emit(this.word, {count: 1})
        }
        """
    
    def reduce = """
        function reduce(key, values) {
            var count = 0
            for (var i = 0; i < values.length; i++)
                count += values[i].count
            return {count: count}
        }
        """
    
    def finalize = """
        function finalize(key, reducedValue) {
            return {count: reducedValue.count.toString()}
        }
        """
    
    def command = new MapReduceCommand(db.words, map, reduce, 'mrresult', MapReduceCommand.OutputType.REPLACE, new BasicDBObject())
    
    command.setFinalize(finalize)
    
    db.words.mapReduce(command)
    
    println db.mrresult.findOne()