MongoDB mapReduce多键值计数问题



让我解释一下我的问题。所以我在MongoDB中运行简单的mapReduce查询,我得到了非常奇怪的结果,对我来说没有任何意义。也许有人会解释它或找到一些错误。所以…

我正在运行2.6.2版本的mongoDB集合中的每个文档都有结构(我有~2000个文档)

{
  _id:...,
  data:{
    type:'myType'
  }
}

map function

var map = function() {
  if(this.data.type== 'myType123') {
    emit(this.data.type, {count:1});
  }
}

减少功能

var reduce = function(keyCustId, allElems) {
  var res = {};
  res.example = allElems;
  return res;
}

我试着运行

var results = db.myCollection.mapReduce( map, reduce,{ out: "map_reduce_example" });

现在检查结果db[results.result].find().pretty();为什么MONGO让结果如此嵌套??是我的地图或减少函数是错误的??如果在map->emit(key, value)中,我传递的值不是作为对象,而是一个整数,一切工作正常。请帮我解决这个mongoDB的噩梦,谢谢。

{
_id:'myType123',
value:{
  example:[
   {count:1},
   {count:1},
   {count:1},
   {count:1},
   {example: [
     {count:1},
     {count:1}, 
     {example:[
        {count:1},
        {count:1},
        {count:1}
     ]
   ]
   }
  ]
}
}

您错过了文档中的重要概念,它引用了:

"MongoDB可以对同一个键多次调用reduce函数。在这种情况下,该键的reduce函数先前的输出将成为该键的下一次reduce函数调用的输入值之一。"

,后来:

"…返回对象的类型必须与map函数发出的值的类型相同。"

这意味着你必须从你的"reduce"操作返回本质上相同的数据签名,因为你从你的"map"函数。这是因为mapReduce不会一次为一个键"减少"所有文档。它是分步骤完成的。

所以被"部分还原"的东西可以再次被reduce函数调用。它实际上一次处理大约30个左右的项目,并且由于您的"reduce"不会发出与"map"相同的输出,因此在下一次访问reducer时,数据的处理方式不同。

这就是为什么你的结果会出现。为了解决这个问题,reduce需要输出与"input"中预期的相同的"类型"的数据:

var reduce = function(key, values) {
  var res = { "count": 0 }
  values.forEach(function(value) {
      res.count += value.count;
  });
  return res;
}

因为输出和输入的数据是一样的,所以你要正确地"计数"你的键出现

相关内容

  • 没有找到相关文章

最新更新