Java – how to calculate an average using mongodb and numberlong

I tried to use the mongodb Java driver to calculate the average value of the collection, as follows:

DBObject condition = 
    new BasicDBObject("pluginIdentifier",plugin.getIdentifier());

DBObject initial = new BasicDBObject();

initial.put("count",0);
initial.put("totalDuration",0);
String reduce = "function(duration,out) { out.count++; 
    out.totalDuration+=duration.floatApprox; }";
String finalize = "function(out) { out.avg = out.totalDuration.floatApprox / 
    out.count; }";

DBObject avg = durationEntries.group(
    new BasicDBObject("pluginIdentifier",true),condition,initial,reduce,finalize);

System.out.println(avg);

"Duration" is numberlong (in Java, it is a long, which may be converted by the Java driver) After some searching, I found that in order to extract numbers, I used Floatapprox is a method that also applies to the mongodb console:

> db.DurationEntries.findOne().duration.floatApprox
5

However, running the Java code above does not calculate the average, but returns it

[{"pluginIdentifier":"dummy","count":7.0,"totalDuration":NaN,"avg":NaN}]

I tried several variants, with and without Floatapprox, but until now we can't get some strange string connections

My question is: what did I do wrong / how should I calculate the average value of a numberlong column?

Solution

If you have a map / reduce problem, you should probably go to the mongodb console, operate there, and then convert it to your driver

For example, the following documents:

db.tasks.find()
{ "_id" : ObjectId("4dd51c0a3f42cc01ab0e6506"),"duration" : 10,"name" : "StartProcess","date" : "20110501" }
{ "_id" : ObjectId("4dd51c0e3f42cc01ab0e6507"),"duration" : 11,"date" : "20110502" }
{ "_id" : ObjectId("4dd51c113f42cc01ab0e6508"),"duration" : 12,"date" : "20110503" }

You can write MapReduce to calculate the average duration of startprocess, as follows:

m = function (){
  emit( this.name,{ totalDuration : this.duration,num : 1 } );
};

r = function (name,values){
  var n = {totalDuration : 0,num : 0};
  for ( var i=0; i<values.length; i++ ){
    n.totalDuration += values[i].totalDuration;
    n.num += values[i].num;
  }
  return n;
};

f = function(who,res){
  res.avg = res.totalDuration / res.num;
  return res;
};

Then, suppose you are using mongodb 1.7 or later:

db.tasks.mapReduce( m,r,{ finalize : f,out : {inline : 1} });

Will give you the following answers:

"results" : [
  {
    "_id" : "StartProcess","value" : {
        "totalDuration" : 33,"num" : 3,"avg" : 11
      }
  }
]

If this does not help, you can publish your map features and document structure

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>