MongoDB Map / Reduce Array聚合问题

如何解决MongoDB Map / Reduce Array聚合问题

| 我有一个MongoDB集合,其文档使用了多个层次的嵌套,我希望从中提取从其字段子集编译的多维数组。我有一个适合我的解决方案,但是我想更好地理解“幂等”的概念及其与reduce函数相关的后果。
{
  \"host_name\" : \"gateway\",\"service_description\" : \"PING\",\"last_update\" : 1305777787,\"performance_object\" : [
    [ \"rta\",0.105,\"ms\",100,500,0 ],[ \"pl\",\"%\",20,60,0 ]
  ]
}
这是map / reduce函数
var M = function() {
  var hn = this.host_name,sv = this.service_description,ts = this.last_update;
  this.performance_object.forEach(function(P){
    emit( { 
      host: hn,service: sv,metric: P[0] 
    },{ 
      time: ts,value: P[1] 
    } );
  });
}
var R = function(key,values) {
  var result = { 
    time: [],value: [] 
  };
  values.forEach(function(V){
    result.time.push(V.time);
    result.value.push(V.value);
  });
  return result;
}
db.runcommand({
  mapreduce: <colname>,out: <col2name>,map: M,reduce: R
});
数据以有用的结构返回,我将其格式化/排序并最终确定图形。
{
  \"_id\" : {
    \"host\" : \"localhost\",\"service\" : \"disk Space\",\"metric\" : \"/var/bck\"
  },\"value\" : {
    \"time\" : [
      [ 1306719302,1306719601,1306719903,... ],[ 1306736404,1306736703,1306737002,[ 1306766401,1306766701,1306767001,... ]
    ],\"value\" : [
      [ 122,23423,25654,[ 336114,342511,349067,[ 551196,551196,... ]
    ]
  }
}
最后...
 [ [1306719302,122],[1306719601,23423],[1306719903,25654],... ]
TL; DR:阵列结果中出现“块化”的预期行为是什么? 我知道,在发射值的数组上可以多次调用reduce函数,这就是为什么完整数组中有多个“块”而不是单个数组的原因。数组块通常为25至50个项目,并且很容易在finalize()中清除它。我concat()数组,将它们交织为[time,value]并排序。但是我真正想知道的是,这是否会变得更加复杂: 1)是否因为我的代码,MongoDB的实现或Map / Reduce算法本身而发现了分块? 2)在分片配置中是否会出现更深(递归)的数组块嵌套,甚至仅仅是因为我的草率实现?这将破坏concat()方法。 3)是否有一个更好的策略来获得如上所述的数组结果? 编辑:修改为发出数组: 我接受了Thomas的建议,并重新编写了它以发出阵列。拆分这些值绝对没有任何意义。
var M = function() {
  var hn = this.host_name,{ 
      value: [ ts,P[1] ] 
    } );
  });
}
var R = function(key,values) {
  var result = {
    value: [] 
  };
  values.forEach(function(V){
    result.value.push(V.value);
  });
  return result;
}
db.runcommand({
  mapreduce: <colname>,reduce: R
});
现在输出类似于:
{
  \"_id\" : {
    \"host\" : \"localhost\",\"value\" : {
    \"value\" : [
      [ [1306736404,336114],[1306736703,342511],[1306737002,349067],[ [1306766401,551196],[1306766701,[1306767001,[ [1306719302,... ]
    ]
  }
}
然后,我使用了这个finalize函数来连接数组块并对它们进行排序。
...
var F = function(key,values) {
  return (Array.concat.apply([],values.value)).sort(function(a,b){ 
    if (a[0] < b[0]) return -1;
    if (a[0] > b[0]) return 1;
    return 0;
  });
}
db.runcommand({
  mapreduce: <colname>,reduce: R,finalize: F
});
哪个很好用:
{
  \"_id\" : {
    \"host\" : \"localhost\",\"metric\" : \"/mnt/bck\"
  },\"value\" : [ [1306719302,... ]
}
我猜唯一一个困扰我的问题是,是否可以始终信任此Array.concat.apply([],values.value)来清理reduce的输出。 最后编辑:更简单... 自从上面给出原始示例以来,我已经修改了文档结构,但这仅通过使map函数真正简单来更改示例。 我仍在努力地思考为什么Array.prototype.push.apply(result,V.data)的工作原理与result.push(V.data)如此不同...但是可以工作。
var M = function() {
  emit( { 
    host: this.host,service: this.service,metric: this.metric
  },{ 
    data: [ [ this.timestamp,this.data ] ] 
  } );
}
var R = function(key,values) {
  var result = [];
  values.forEach(function(V){
    Array.prototype.push.apply(result,V.data);
  });
  return { data: result };
}
var F = function(key,values) {
  return values.data.sort(function(a,b){
    return (a[0]<b[0]) ? -1 : (a[0]>b[0]) ? 1 : 0;
  });
}
它具有与LAST EDIT标题上方相同的输出。 谢谢,托马斯!     

解决方法

         \“ chunking \”来自您的代码:reduce函数的values参数可以包含map函数发出的
{time:<timestamp>,value:<value>}
,或先前调用reduce函数返回的
{time:[<timestamps>],value:[<values]}
。 我不知道它是否会在实践中发生,但它可以在理论上发生。 只需让您的map函数发出与reduce函数返回的对象相同的对象(即
emit(<id>,{time: [ts],value: [P[1]]})
),并相应地更改reduce函数(即
Array.push.apply(result.time,V.time)
)和类似的
result.value
。 好吧,我实际上不明白为什么您不使用时间/值对数组而不是数组,即map函数中的function14ѭ或
emit(<id>,{ pairs: [ [ts,P[1]] ] })
以及reduce函数中的
Array.push.apply(result.pairs,V.pairs)
。这样,您甚至不需要finalize函数(可能要从pairs属性“解包”数组:因为reduce函数无法返回数组,因此您必须将其包装在对象中)     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?