MongoDB 使用 map_reduce,但是结果有问题。

lukefan · 2014年02月04日 · 最后由 saharaying 回复于 2014年03月14日 · 8368 次阅读

我有一个数据库,里面有九百多条资源信息。并对这九百多条信息,标记了两千多个标签。 于是写了一个 map_reduce,计算每个 tag 从属的资源数量。 一开始是使用 count 进行累加的,结果发现很多数字都比实际结果多了一倍,也就是说有些标签,只有一个资源标注了,但是统计的结果却是二。 于是,我就将统计 count 的方式,改成了累计_id,结果发现确实是将很多数据重复记录了,但也不是每次都这样。于是在记录的时候,再加上了去重的指令,结果依然无效。 代码如下:

map = %Q{
      function() {
        var id = this._id;
        this.tag_ids.forEach(function(tag_id) {
          emit(tag_id, {
            resources: [id]
            })
          })
      }
    }
    reduce = %Q{
      function(key, values) {
        var result = {
          resources: [],
        };
        values.forEach(function(value) {
          value.resources.forEach(function(resource){
            if (result.resources.indexOf(resource) == -1)
            {
              result.resources.push(resource);
            }
            });
          });
        return result;
      }
    }
    Resource.map_reduce(map, reduce).out(inline: true);

请帮忙看看。

全部代码:https://gitcafe.com/lukefan/test6 上面的函数在:https://gitcafe.com/lukefan/test6/blob/master/app/models/resource.rb

有人帮忙看看吗?

挺神奇,还能写 js 代码

老范,你这个代码我没看懂,我怀疑是:indexOf 与变量类型的问题。建议你输出些日志看看。

#3 楼 @zhuangbiaowei 经过测试,ObjectId(*),之后的值,确实是没办法用 indexOf 进行索引。这个函数在 ObjectId 的数组中,永远返回 -1。 按道理说,没有必要做这一步的,MapReduce 本身就不应该把重复的数据进行累加。

这点数据 Excel 都能算了吧 ...

#5 楼 @bhuztez 只是尝试一下 MongoDB 的 MapReduce,没想到得到的结果是错误的。

这个,map_reduce 用 inline 的,不如直接用 aggregate 啊,$unwind + $group 就搞定了

需要 登录 后方可回复, 如果你还没有账号请 注册新账号