【问题标题】:mongodb, calculate result after mapreducemongodb,mapreduce后计算结果
【发布时间】:2014-12-17 16:36:24
【问题描述】:

我有 mapreduce 函数来分组和计算一些字段

map = %Q{
  function() {
    emit({ip: this.ip, campaign_id: this.campaign_id}, {total_count: 1, total_commission: this.commission, uniq_commission: 0});
  }
}

reduce = %Q{
  function(key, values) {   
    var total_commission = 0; 
    values.forEach(function(value) {
      total_commission += value.total_commission; // to sum 
    });        
    return {total_count: values.length, total_commission: total_commission, uniq_commission: values[0]["total_commission"]};
  }
}

输出如下:

[
{"_id":{"ip":"39.49.65.101","campaign_id":{"$oid":"548121156e6f62101f000000"}},"value":   {"total_count":1.0,"total_commission":1.0,"uniq_commission":0.0}},

{"_id":{"ip":"39.49.65.102","campaign_id":{"$oid":"548121156e6f62101f000000"}},"value":{"total_count":5.0,"total_commission":1.0,"uniq_commission":0.0}},

{"_id":{"ip":"39.49.65.103","campaign_id":{"$oid":"548121156e6f62101f000000"}},"value":{"total_count":3.0,"total_commission":1.0,"uniq_commission":0.0}},

...
]

我想这样计算:

result = {}
obj.map_reduce(map, reduce).out(inline: true).each do |r|
   result["total_count"] += r["value"]["total_count"]
   result["total_commission"] += r["value"]["total_commission"]
   result["uniq_count"] += 1 
   result["uniq_commission"] += r["value"]["uniq_commission"]
end

这个函数用大数据库计算需要很长时间 50.000 条记录 ~ 40 秒

这种情况有什么解决办法吗? 我希望我可以访问一些全局 obj 来处理这个 ^_^

编辑: 部分数据示例:

<Transaction _id: 5491a66e6e6f620ff4f74d00, commission: 1.0, total_cost: 200.0, order_id: "Order-1418831470", ip: "11.11.11.11", referer_url: nil, campaign_id: BSON::ObjectId('548121156e6f62101f000000'), affiliate_id: BSON::ObjectId('5472dea46e6f62236c060000'), rawclick_id: BSON::ObjectId('5491a66e6e6f620ff4f64d00'), _keywords: ["123213", "abc", "company", "last", "name", "organization"]> 


<Transaction _id: 5491a66e6e6f620ff4f74d11, commission: 1.0, total_cost: 200.0, order_id: "Order-1418831470", ip: "11.11.11.11", referer_url: nil, campaign_id: BSON::ObjectId('548121156e6f62101f000000'), affiliate_id: BSON::ObjectId('5472dea46e6f62236c060000'), rawclick_id: BSON::ObjectId('5491a66e6e6f620ff4f64d00'), _keywords: ["123213", "abc", "company", "last", "name", "organization"]> 


<Transaction _id: 5491a66e6e6f620ff4f74d22, commission: 1.0, total_cost: 200.0, order_id: "Order-1418831470", ip: "22.22.22.22", referer_url: nil, campaign_id: BSON::ObjectId('548121156e6f62101f000000'), affiliate_id: BSON::ObjectId('5472dea46e6f62236c060000'), rawclick_id: BSON::ObjectId('5491a66e6e6f620ff4f64d00'), _keywords: ["123213", "abc", "company", "last", "name", "organization"]> 


<Transaction _id: 5491a66e6e6f620ff4f74d33, commission: 1.0, total_cost: 200.0, order_id: "Order-1418831470", ip: "33.33.33.33", referer_url: nil, campaign_id: BSON::ObjectId('548121156e6f62101f000000'), affiliate_id: BSON::ObjectId('5472dea46e6f62236c060000'), rawclick_id: BSON::ObjectId('5491a66e6e6f620ff4f64d00'), _keywords: ["123213", "abc", "company", "last", "name", "organization"]> 


<Transaction _id: 5491a66e6e6f620ff4f74d44, commission: 1.0, total_cost: 200.0, order_id: "Order-1418831470", ip: "96.9.32.51", referer_url: nil, campaign_id: BSON::ObjectId('548121156e6f62101f000000'), affiliate_id: BSON::ObjectId('5472dea46e6f62236c060000'), rawclick_id: BSON::ObjectId('5491a66e6e6f620ff4f64d00'), _keywords: ["123213", "abc", "company", "last", "name", "organization"]> 

【问题讨论】:

  • 你能给我们展示一个示例输入数据集(比如 5 行)吗?您应该先index 您的数据然后运行 ​​mapreduce 或聚合 - 取决于数据的性质以及您是否在单台/多台计算机上执行此操作。
  • 我在下面进行了一些编辑。如果我使用 sub mapreduce 会更低吗?请帮我找出这个语法stackoverflow.com/questions/27538524/…

标签: ruby-on-rails mongodb mapreduce mongoid


【解决方案1】:

如果我正确阅读了您的 map/reduce,那么您所做的就是计算按 ipcampaign_id 分组的文档的数量和总佣金。我不确定uniq_commission 的目的应该是什么,因为在您的 map/reduce 中,它的最终值取决于 MongoDB 如何执行 map/reduce,并且在其他代码中,它始终为零,因为它求和up 看起来好像都设置为零的值。 - 如果您可以解释其目的,我将尝试修改我的答案以将其考虑在内。不要使用地图/减少。聚合可以进行这种计算,并且比 map/reduce 更快:

db.test.aggregate([
    { "$group" : { "_id" : { "ip" : "$ip", "campaign_id" : "$campaign_id" },
                   "total_count" : { "$sum" : 1 },
                   "total_commission" : { "$sum" : "$commission" }
    } }
])

【讨论】:

  • 是的,你的方式也一样。我用聚合容器 2 组来做。而且效果很好。时间成本是如此惊人:)。感谢您的回答
猜你喜欢
  • 2014-07-18
  • 1970-01-01
  • 2015-03-24
  • 1970-01-01
  • 1970-01-01
  • 2012-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多