2

对于我的 Rails+MongoId 应用程序,我需要汇总数据以用于统计目的。我的模型展示了一个通用的 Web 应用程序,该应用程序具有多个版本(又名:捆绑包)和相关用户激活:

App = {
  "_id" : ObjectId("4ff2e2eab528571384000eb4"),
  "name" : "my app",
  "category_id": "4ff2e2eab528571384000cc0",
  "bundles": [{
    "_id" : ObjectId("4ff2e2eab528571384000dca"),
    "activations" : [{
      "user" : "user_0",
      "_id" : ObjectId("4ff2e2eab528571384000dd0")
     },
     ... 
  },
  ...
  ]
}

现在,我要做的是返回每个应用程序 CATEGORY_ID 的 ACTIVATIONS 数量,例如:

results = [
  {
    "_id": "4ff2e2eab528571384000cc0",
    "value": 243
  },
  ...
]

我可以使用这个 mapreduce 函数轻松获得每个 CATEGORY_ID 的 BUNDLES 总数:

map = function() { 
  for (var bundle in this.bundles) { 
    emit(this.category_id, 1); 
  }
};
reduce = function(key, values) { 
  var sum = 0; 
  values.forEach(function(value) { 
    sum += value; 
  }); 
  return sum; 
};

但是,当我尝试更深入地进入一个级别时,我确实没有得到任何结果:

map = function() { 
  for (var bundle in this.bundles) { 
    for (var activation in bundle.activations) {
      emit(this.category_id, 1); 
    }
  }
};
reduce = function(key, values) {
  var sum = 0; 
  values.forEach(function(value) { 
    sum += value;
  });
  return sum;
};

非常感谢任何想法。此致

迈克·科斯塔

4

2 回答 2

1

感谢NOMOA的提示,

我可以通过如下修改 map 函数来解决我的问题:

map = function() { 
  var len = this.bundles.length; 
  for (var i = 0; i < len; i++) {
    if (this.bundles[i].activations !== undefined) { 
      emit(this.category_id, this.bundles[i].activations.length);
    } 
  }
};

我不得不删除 for..in 结构以支持更传统的 for..i++,添加一个“未定义”检查(如您所建议的那样),它工作得很好(我也避免了双循环)!

最好的问候 M.科斯塔

于 2012-07-04T13:19:40.937 回答
0

你确定你的 map reduce 函数运行正确吗?

我想你应该检查 bundle.activations 是否为非空。检查服务器日志中是否有任何错误。您还可以使用服务器日志查看调试打印语句。

于 2012-07-03T14:23:59.907 回答