MongoDB的嵌套Group功能

时间:2011-05-20 23:57:02

标签: mongodb mongoid mongodb-ruby

对于MongoDB来说,我是一个很新的人,他是一个很长时间的MySQL人,而且遇到了一些障碍。

鉴于以下样本数据:
TeamID Day OrderAmount
100个4/1 50
100个4/1 40
200个4/2 50
100 4/2 20

我正在尝试查找每天的平均团队订单金额。我可以使用mapReduce函数进行一个简单的查询,通过TeamId& amp;天。所以现在我有:

TeamID日AvgAmount
100个4/1 45
200个4/2 50
100个4/2 20

现在我正在努力推广这些数据,以获得每个团队每天的平均订单金额,这将是:

日AvgAmount
4/1 47.5
4/2 35

我可以使用MySQL轻松完成这项工作,但是如果没有在应用程序端手动执行,而不是使用MongoDB进行操作,我很难弄清楚如何使用MongoDB执行此操作。

2 个答案:

答案 0 :(得分:4)

您可以使用map-reduce或group()函数计算这些聚合。我正在使用group(),因为它更简单,更快,但如果需要在分片集群上分发查询,则应使用map-reduce。

首先加载数据:

db.orders.insert( { teamid: 100, date: "4/1", amount: 50 })
db.orders.insert( { teamid: 100, date: "4/1", amount: 40 })
db.orders.insert( { teamid: 200, date: "4/2", amount: 50 })
db.orders.insert( { teamid: 100, date: "4/2", amount: 20 })

每个团队,每天:

db.orders.group({
    key: { teamid: true, date: true },
    reduce: function(doc, out) { out.sum += doc.amount; out.count++; },
    initial: { sum: 0, count: 0 },
    finalize: function(out) { out.average = out.sum / out.count }
});

要汇总每日汇总数,只需更改密钥:

db.orders.group({
    key: { date: true },
    reduce: function(doc, out) { out.sum += doc.amount; out.count++; },
    initial: { sum: 0, count: 0 },
    finalize: function(out) { out.average = out.sum / out.count }
});

答案 1 :(得分:0)

经过一番研究,我得出了一个解决方案。我不满足于它是最优化的解决方案,因为它是MongoDB的新手并且映射/减少思维,所以如果其他人有更好的东西,请纠正我。具体来说,我无法获得一定长度的arr_team对象,所以我必须有一个递增的计数器。

减少功能:


    function(doc, prev) { 
      var retVal  = {team_count: 0, day_total: 0};

      if(!prev.arr_team[doc.team_id]) {
        prev.arr_team[doc.team_id] = 0;
        prev.team_count++;
      }

      prev.arr_team[doc.team_id]++;

      prev.order_count++; 
      if(doc.total_amount)
         prev.total_amount += doc.total_amount 

      return retVal;
    }

敲定:


function(out) {
      out.avg_team_order_amount = out.total_amount/out.team_count;
    }