3

我正在尝试在我的一个 MongoDB 数据库集合上创建一个简单的 map/reduce 函数。我得到了数据,但它看起来不对。我不确定地图部分。我可以这样使用 IF/ELSE 吗?

更新

我想获得拥有这些文件的作者数量。换句话说,有多少作者拥有上传的文件,因此有多少作者没有文件。

集合中的对象如下所示:

{
    "_id": {
        "$id": "4fa8efe33a34a40e52800083d"
    },
    "file": {
        "author": "john",
        "type": "mobile",
        "status": "ready"
    }
}

map/reduce 看起来像这样:

$map = new MongoCode ("function() {

if (this.file.type != 'mobile' && this.file.status == 'ready') {

 if (!this.file.author) {

  return;

 }

 emit (this.file.author, 1);

}

}");

$reduce = new MongoCode ("function( key , values) {

 var count = 0;

 for (index in values) {

  count += values[index];

 }

 return count;

}");

$this->cimongo->command (array (

 "mapreduce" => "files",  

 "map"       => $map,   

 "reduce"    => $reduce,  

 "out"       => "statistics.photographer_count"

)

);
4

2 回答 2

1

地图部分在我看来还可以。我会稍微改变减少部分。

values.forEach(function(v) {
  count += v;
}

你不应该使用循环for in来迭代一个数组,它不是为了这样做。它用于枚举对象的属性。这里有更详细的解释。

为什么你认为你的数据是错误的?你的源数据是什么?你得到了什么?你期望得到什么?

于 2012-07-20T10:03:50.520 回答
1

我刚刚尝试了您的地图并在 mongo shell 中减少并得到了正确(看起来合理)的结果。

您可以做的另一种方法是摆脱地图中的内部“if”条件,但使用适当的查询子句调用您的 mapreduce 函数,例如:

db.files.mapreduce(map,reduce,{out:'outcollection', query:{"file.author":{$exists:true}}})

或者,如果您碰巧有索引来提高查询效率,只需摆脱所有 if 并运行 mapreduce withquery:{"file.author":{$exists:true},"file.type":"mobile","file.status":"ready"}子句。更改条件以匹配您要总结的实际案例。

在 2.2(即将推出的 rc0 版本)中,您可以将聚合框架用于此类查询,而不是编写 map/reduce 函数,希望这会在某种程度上简化事情。

于 2012-07-21T19:31:11.113 回答