如何使用 mongodb 和 NumberLong 计算平均值

发布于 2024-10-14 15:06:56 字数 1085 浏览 3 评论 0原文

我正在尝试使用 mongodb java 驱动程序计算集合的平均值,如下所示:

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”是一个 NumberLong (在 java 中,它是一个 Long,可能是 java 驱动程序转换它)。 经过一番搜索后我发现,为了提取数字,使用 .floatApprox 是一种方法,这也适用于 mongodb 控制台:

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

但是,运行上面的 java 代码不会计算平均值,而是返回平均值

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

我尝试了几种变体,有或没有 .floatApprox,但到目前为止只能获得一些奇怪的字符串连接。

我的问题是:我做错了什么/我应该如何计算一个 NumberLong 列的平均值?

I am trying to compute an average value from a collection using the mongodb java driver, like this:

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 a NumberLong (in java, it is a Long, probably the java driver converts it).
I figured out after some searching that in order to extract the number, using .floatApprox was one way to go, and this also works in the mongodb console:

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

However, running the above java code won't compute an average, but returns this instead

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

I tried several variations, with and without .floatApprox, but have only been able to obtain some weird string concatenations until now.

My question is: what am I doing wrong / how should I go about to calculate the average of one NumberLong column?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

寂寞清仓 2024-10-21 15:06:56

如果您在使用 map/reduce 时遇到问题,您可能应该进入 mongodb 控制台,在那里解决问题,然后将其转换为您的驱动程序。

以以下文档为例:

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

您将编写 mapReduce 来计算 StartProcess 的平均持续时间,如下所示:

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;
};

然后,假设您使用的是 MongoDB 1.7 或更高版本:

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

将为您提供以下答案:

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

如果这没有帮助,你能发布你的地图功能和文档结构吗?

If you're having problems with map/reduce you should probably drop down into the mongodb console, work it out there and then translate that into your driver.

Take, for example, the following documents:

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

You would write the 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, assuming you're using MongoDB 1.7 or above:

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

Would give you the following answer:

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

If this doesn't help, can you post your map function and document structure.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文